C#编程技巧-高性能、避免异常、代码简洁-(长期更新)

文件系统

文件、文件夹目录重命名官方方法

C# File类中是没有rename这个方法,但可以使用vb.net中的My.Computer.FileSystem.RenameFile方法

  1. 先添加引用:Microsoft.VisualBasic,再加上using Microsoft.VisualBasic.Devices;
  2. 代码如下:
Computer MyComputer = new Computer();
//file是你所要重命名的文件的全路径,newName是重命名的目标文件名;
MyComputer.FileSystem.RenameFile(file, newName);
//directory要重命名的目录的路径和名称,newName目录的新名称
MyComputer.FileSystem.RenameDirectory(directory, newName);

其中FileName是你所要重命名的文件的全路径,newFileName仅仅是目标文件名;

UI控件

子线程操作UI控件,一行代码完成

可根据实际需求修改以下代码

//方法1
label1.Invoke(new EventHandler(delegate {label1.Text = "更改控件属性,传入的有sender、e两个参数";}));
//方法2
label1.Invoke(new Action(()=> {label1.Text = "更改控件属性2,也可执行其它操作";}));

命名规范

类名、方法名、属性名、事件名全部使用Pascal命名法,即所有单词连写,每个单词的第一个字母大写,其他字母小写。例如:HelloWorld、GetData等。
变量名、对象名、方法的参数名 全部使用Camel命名法,即所有单词连写,但是第一个单词全部小写,其他每个单词的第一个字母大写。

exe调用

通过Process调用cmd运行控制台程序,根据不同输入获取返回结果

        //如果exe放在主程序exe启动目录下,则command为待调用的exe程序的名称(不需要.exe后缀)
        static string cmd(string command)  
        {  
            Process pro = null;  
            
            string result = string.Empty;  
            try  
            {  
                pro = new Process();  
                pro.StartInfo.FileName = "cmd.exe";             //cmd  
                pro.StartInfo.UseShellExecute = false;          //不显示shell  
                pro.StartInfo.CreateNoWindow = true;            //不创建窗口  
                pro.StartInfo.RedirectStandardInput = true;     //打开流输入  
                pro.StartInfo.RedirectStandardOutput = true;    //打开流输出  
                pro.StartInfo.RedirectStandardError = true;     //打开错误流  
 
                pro.Start();//执行  
                
                pro.StandardInput.WriteLine(command + "&exit");      //&exit运行完立即退出  
                pro.StandardInput.AutoFlush = true;             //清缓存  
   
                StreamReader reader = pro.StandardOutput;//截取输出流
                StreamReader error = pro.StandardError;//截取错误信息
                
                result = reader.ReadToEnd() + error.ReadToEnd();  //读取输出                
                result=result.Replace("\r\n\r\n","\r\n").Replace("\r\n\r\n","\r\n");//去除空行
 
                result = pro.StandardOutput.ReadToEnd();            //读取输出 
 
                pro.WaitForExit();                              //等待程序执行完退出进程  
 
                pro.Close();//结束  
 
                return result;  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine(Exception Occurred :{0},{1}, ex.Message, ex.StackTrace.ToString());  
                return ex.Message.ToString();  
            }  
        }  

枚举

C# 获取 Enum 枚举的 Description 描述内容

通过反射获取枚举类的Field,再用 Field 获取 DescriptionAttribute 属性。

// 枚举
public enum enumStudent
{
    [Description("性别")]
    sex = 0,
    [Description("年龄")]
    age = 1,
}
 
// 获取方法
public string GetDescriptionByEnum(Enum enumValue)
{
    string value = enumValue.ToString();
    System.Reflection.FieldInfo field = enumValue.GetType().GetField(value);
    object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false);    //获取描述属性
    if (objs.Length == 0)    //当描述属性没有时,直接返回名称
        return value;
    DescriptionAttribute descriptionAttribute = (DescriptionAttribute)objs[0];
    return descriptionAttribute.Description;
}

字符串

转化字符串为基本数值类型时使用TryParse(),避免使用Parse()

代码如下:

double d;
string str="18";
double.TryParse(str, out d)
//使用TryParse转换时没有异常,转换失败返回0

测试的结果如图:
在这里插入图片描述
所用测试代码:https://blog.csdn.net/FliesOfTime/article/details/102566863

使用FileShare避免写日志文件时出现"正由另一进程使用,因此该进程无法访问该文件"异常

写日志文件经常出现"正由另一进程使用,因此该进程无法访问该文件",这是因为上次读写文件还没有关闭就请求下一次读写,可使用FileShare解决。以下为解决方法:

public static void WriteLog(string _msg)
    {
        string filename = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DateTime.Now.ToShortDateString() + ".txt"); ;
        if (File.Exists(filename))
        {
            FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter sr = new StreamWriter(fs);
            sr.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "\t" + _msg);
            sr.Close();
            fs.Close();
        }
        else
        {
            FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
            StreamWriter sr = new StreamWriter(fs);
            sr.WriteLine(DateTime.Now.ToString("HH:mm:ss") + "\t" + _msg);
            sr.Close();
            fs.Close();
        }       
    }
 

FileShare.ReadWrite:允许随后打开文件读取或写入。 如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。 但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件

连接字符串

“+”和Append的区别

“+”和Append的功能都一样(连接字符串),两者之间的区别在于执行效率上面的问题。Append构建字符串的效率比使用“+”连接的高,如果有较多的字符串需要拼接建议使用Append进行拼接,少的话使用“+”更方便阅读

//推荐使用
StringBuilder sbr = new StringBuilder();
sbr.Append("显示");
sbr.Append("信息");
string str=sbr.Append(localPort.ToString());

//效率低,不推荐
string str="显示"+"信息";

Append和AppendLine的区别

Append和AppendLine的区别:Append是不加回车的拼接(追加);AppendLine是加回车的拼接(追加)。

byte字节

读、写byte字节中某一位的值

//index从0开始 
//获取取第index位 
public static int GetBit(byte b, int index) { return ((b & (1 << index)) > 0) ? 1: 0; }
//将第index位设为1 
public static byte SetBit(byte b, int index) { return (byte)(b | (1 << index)); }
//将第index位设为0 
public static byte ClearBit(byte b, int index) { return (byte)(b & (byte.MaxValue - (1 << index))); }
//将第index位取反 
public static byte ReverseBit(byte b, int index) { return (byte)(b ^ (byte)(1 << index)); }

类型转换

使用is与as(推荐使用as)代替直接强制转换

强制类型转换,有可能会导致异常,is与as就是为了解决这一问题。

  • is与as永远不会抛出异常
  • is判断一个对象是否兼容于指定的类型,考虑里氏代换(子类能转换为基类,基类不能转换为子类)
  • as 与强制类型转换一样,区别是使用as是安全的。使用as如果转换失败,返回Null,不会抛出异常。

使用is和as可以取代强制类型转换,分别如下:

 if(a is ClassB)
 {
     ClassB d = (ClassB)a;
     //业务代码
 }
 
 Dog d = a as Dog;
  if(d!=null)
  {
   //业务代码
 }

两种方法效果一样,但是效率差别很大,使用is会检查两次对象的类型,一次是核实,一次是强制转换。使用as只进行了一次对象类型的检查。检查对象的类型,是个耗费资源的操作,首先要判断对象的实际类型,然后必须遍历继承树结构(层次结构),去与每个基类核对。
 编程时应避免多余的类型检查,推荐使用as进行类型转换。

多线程

使用Lambda表达式简化线程池的使用

使用线程池时要定义线程池回调方法,使用Lambda表达式可以直接将一些操作放入线程池执行而不用另外定义方法

//在线程池执行xxx方法,传入参数objData
ThreadPool.QueueUserWorkItem(((obj) =>
{
    XXX((byte[])obj);
}), objData);

在线程池执行xxx方法,无传入参数
ThreadPool.QueueUserWorkItem((obj) =>
{
    xxx();
});

对象实例

在初始化对象实例的时候,为指定的属性赋值

可在对象初始化时直接给属性赋值,代码如下;

DemoClass dc = new DemoClass () { Name =“李四”};
Console.WriteLine(dc.Name);//输出 李四

编程技巧

快速生成不重复的随机数(随机索引取List)

方法:先顺序生成所要的所有随机数,然后随机索引取出。

public static void Main(string[] args)
 {
     List<int> array = new List<int>();
     int range = 100;
     for (int i = 0; i < range; i++)
     {
         array.Add(i);
     }
     var random = new Random();
     for (int i = 0; i < range; i++)
     {
         var index = random.Next(0, array.Count);
         var value = array[index];
         array.RemoveAt(index);
         Console.Write(value + " ");
     }
 }

写大文件策略:先建一个大文件,然后再向里面追加数据

创建超大文件代码如下:

FileStream fs = new FileStream(@"D:\tmp\test_file", FileMode.CreateNew);
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();

读写TSV / TAB 文件

TSV / TAB 文件全称为Tab-separated values,即用制表符的方式来存储文件。(char(9) 水平制表符)

//写TSV文件
TextWriter writer = new StreamWriter(@"C:\test.csv");
writer.WriteLine(String.Join("\t", new[] { "abc", "def" }));
writer.WriteLine(String.Join("\t", new[] { "123", "456" }));
writer.Close();

//读TSV文件
using (StreamReader reader = new StreamReader(@"C:\test.csv"))
{
  string line;
  while ((line = reader.ReadLine()) != null)
  {
    string[] a = line.Split(new char[] { (char) 9 });
    Console.WriteLine(a[0]);
  }
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C是计算机科学中的一种编程语言。它是由丹尼斯·里奇在20世纪70年代初开发的。C语言具有高度的可移植性和效率,因此广泛应用于操作系统、编译器和嵌入式系统等领域。 C语言是一种结构化的编程语言,它使用简洁的语法和底层的控制结构,可以高效地操作内存和处理底层硬件。C语言具有丰富的数据类型、运算符和库函数,可以实现各种任务。 C语言被广泛认为是学习编程的入门语言,因为它易于学习和理解。通过学习C语言,人们可以掌握程序设计的基本概念,如变量、循环、条件语句和函数等。这对于理解更高级的编程语言和算法是至关重要的。 C语言的优点之一是它的可移植性。由于C语言的设计初衷是为了编写操作系统,它在不同的机器和操作系统上都能够很好地运行。这使得开发人员可以轻松地将他们的代码移植到不同的平台上,节省了大量的工作和时间。 另外,C语言的效率也是它的一个优点。由于C语言可以直接访问内存和底层硬件,所以它可以高效地运行,处理大量的数据和复杂的计算。这使得C语言在需要快速和高效的任务中得到广泛应用,如嵌入式系统和科学计算等领域。 总的来说,C语言是一种强大而灵活的编程语言,具有高度的可移植性和效率。它是计算机科学领域中必备的工具,对于学习编程和实现高性能的应用程序都具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值