热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#一些代码细节规范

这篇文章的起因是因为看到很多项目在设计上和功能实现上都很高大上,但是一


这篇文章的起因是因为看到很多项目在设计上和功能实现上都很高大上,但是一些细节代码却不堪入目。本文准备从代码细节上规范代码。

此文不涉及命名规范和注释规范。另外如果有不实之处还望在评论区指出。

 

一、禁止使用加号拼接字符串

项目中总是看到用+号去拼接字符串,但是我觉得完全可以用string.Concat()、string.Format()、StringBuilder、$string.Join 等方式替代用加号拼接字符串。

原因:无论是从性能上还是可读性来说都比+号好一点。

反例

string str = "欢迎您,";
string name = "碌云";
str
+= name;
Console.WriteLine(str);

string name = "碌云";
Console.WriteLine(
"欢迎您," + name);

string str = "欢迎您,";
string name = "碌云";
StringBuilder stringBuilder
= new StringBuilder();
stringBuilder.Append(
"");
stringBuilder.Append(str
+ name);
stringBuilder.Append(
"
");
Console.WriteLine(stringBuilder.ToString());

正例

string name = "碌云";
Console.WriteLine(
string.Concat("欢迎您,", name));

string name = "碌云";
Console.WriteLine($
"欢迎您,{name}");

string str = "欢迎您,";
string name = "碌云";
StringBuilder stringBuilder
= new StringBuilder();
stringBuilder.Append(
"");
stringBuilder.AppendFormat(
"{0}{1}", str, name);
stringBuilder.Append(
"
");
Console.WriteLine(stringBuilder.ToString());

 

二、能用string.Empty的地方禁止用""

原因:使用string.Empty比“”快。

反例:

public void GetUserInfoById(string id)
{
if (id == "")
{
throw new Exception("ID不能为空");
}
}

string str = "aaaaaaaa11111111aaaaa";
Console.WriteLine(str.Replace(
"1", ""));

正例:

public void GetUserInfoById(string id)
{
if (id == string.Empty)
{
throw new Exception("ID不能为空");
}
}

string str = "aaaaaaaa11111111aaaaa";
Console.WriteLine(str.Replace(
"1", string.Empty));

 

三、继承自IDisposable的非静态类一定要释放,能用using释放就必须用using

为什么是非静态类呢...因为我之前用.netcore发邮件的类也给它释放了,结果第二次发不了邮件了,所以静态的类还是不要释放了。。

原因:非托管资源必须手动释放,using做了优化:哪怕内部报错了还是会释放 。

反例:

///


/// MD5加密
///

public string MD5Encrypt(string plainText)
{
return BitConverter.ToString(new MD5CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(plainText))).Replace("-", string.Empty);
}

正例:

///


/// MD5加密
///

public string MD5Encrypt(string plainText)
{
using (var md5c = new MD5CryptoServiceProvider())
{
return BitConverter.ToString(md5c.ComputeHash(Encoding.Default.GetBytes(plainText))).Replace("-", string.Empty);
}
}

 

四、禁止嵌套使用using释放资源

可以使用连续using或者利用IDisposable中介的方式释放资源

原因:听说嵌套使用using会造成里面报错外面的释放不了

反例:

private DataSet GetDataSet(string cmdText, CommandType cmdType, params SqlParameter[] parameters)
{
if (string.IsNullOrEmpty(cmdText)) return null;

using (SqlConnection cOnn= GetSqlConnection())
{
using (SqlCommand comm = new SqlCommand())
{
using (SqlDataAdapter adap = new SqlDataAdapter(comm))
{
PrepareCommand(conn, comm, cmdText, cmdType,
null, parameters);
DataSet data
= new DataSet();
adap.Fill(data);
return data;
}
}
}
}

正例:

///


/// 执行命令返回DataSet
///

/// 要执行的命令
/// 命令类型
/// 参数
///
private DataSet GetDataSet(string cmdText, CommandType cmdType, params SqlParameter[] parameters)
{
//如果传入进来的sql是空的则直接return
if (string.IsNullOrEmpty(cmdText)) return null;
//创建数据库连接对象
using (SqlConnection cOnn= GetSqlConnection())
//创建数据命令对象
using (SqlCommand comm = new SqlCommand())
//获取SqlDataAdapter
using (SqlDataAdapter adap = new SqlDataAdapter(comm))
{
//打开数据库连接并初始化命令对象
PrepareCommand(conn, comm, cmdText, cmdType, null, parameters);
//返回的data
DataSet data = new DataSet();
adap.Fill(data);
return data;
}
}

private DataSet GetDataSet(string cmdText, CommandType cmdType, params SqlParameter[] parameters)
{
if (string.IsNullOrEmpty(cmdText)) return null;
SqlConnection conn
= GetSqlConnection();
SqlCommand comm
= new SqlCommand();
SqlDataAdapter adap
= new SqlDataAdapter(comm);
using (IDisposable a = conn, b = comm, c = adap)
{
PrepareCommand(conn, comm, cmdText, cmdType,
null, parameters);
DataSet data
= new DataSet();
adap.Fill(data);
return data;
}
}

 

五、循环内的中间变量声明到循环外面

原因: 放在循环中声明代码会执行多次,放在外面只会声明一次。减少了系统损耗...

反例:

List list = new List();

foreach (var item in paMenus)
{
MenuTreeModel menu
= new MenuTreeModel()
{
href
= item.Url,
icon
= item.Icon,
mid
= item.Mid,
target
= item.Target,
title
= item.Name
};
list.Add(menu);
}

正例:

List list = new List();

MenuTreeModel menu;
foreach (var item in paMenus)
{
menu
= new MenuTreeModel()
{
href
= item.Url,
icon
= item.Icon,
mid
= item.Mid,
target
= item.Target,
title
= item.Name
};
list.Add(menu);
}

 

六、for循环的第二段不要调用方法或者属性

原因:因为每次循环都会进入第二段所以每次访问还是有点效率问题的

反例:

List<string> list = new List<string>() { "碌云" };
for (int i = 0; i )
{
Console.WriteLine(list[0]);
}

正例:

List<string> list = new List<string>() { "碌云" };
for (int i = 0, count = list.Count; i )
{
Console.WriteLine(list[0]);
}

 

七、用运算的方式增加代码可读性

原因:可读性高,(性能损耗可以忽略不计)

反例:

public static async Task Main(string[] args)
{
await Task.Delay(120000);
Console.WriteLine(
"等待两分钟后输出");
}

正例:

public static async Task Main(string[] args)
{
await Task.Delay(1000 * 60 * 2);
Console.WriteLine(
"等待两分钟后输出");
}

 

八、方法禁止返回Task,使用async/await代替返回Task

原因未知,之前在某个博客上看到的。求大佬补充

反例:

public static async Task Main(string[] args)
{
Console.WriteLine(
await GetName());
}

public static Task<string> GetName()
{
return Task.FromResult("碌云");
}

正例:

public static async Task Main(string[] args)
{
Console.WriteLine(
await GetName());
}
public static async Task<string> GetName()
{
return await Task.FromResult("碌云");
}

 

九、不要在循环中使用try/catch,应该把try/catch放到外层

原因:性能更好。具体原因未知,求大佬补充

值得注意的地方就是这样子会导致如果发生错误了循环就进行不下去了,这个实际中还是看业务来吧。

反例:

for (int i = 0; i <100; i++)
{
try
{
Console.WriteLine($
"输出{i + 1}");
}
catch
{
Console.WriteLine(
"输出字符串错误");
}
}

正例:

try
{
for (int i = 0; i <100; i++)
{
Console.WriteLine($
"输出{i + 1}");
}
}
catch
{
Console.WriteLine(
"输出字符串错误");
}

 

十、尽量使用nameof获取名称

原因:可读性强,并且如果被引用的地方发生变更程序会报错,这样就可以一起进行相应的更改。

反例:

public class User

{
public string Name { get; set; }
}
public User EditUser(User user)
{
if (string.IsNullOrEmpty(user.Name))
{
throw new Exception("Name 不能为空");
}
//...省略很多代码
}

正例:

public class User
{
public string Name { get; set; }
}
public User EditUser(User user)
{
if (string.IsNullOrEmpty(user.Name))
{
throw new Exception($"{nameof(User.Name)} 不能为空");
}
//...省略很多代码
}



推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 加密世界下一个主流叙事领域:L2、跨链桥、GameFi等
    本文介绍了加密世界下一个主流叙事的七个潜力领域,包括L2、跨链桥、GameFi等。L2作为以太坊的二层解决方案,在过去一年取得了巨大成功,跨链桥和互操作性是多链Web3中最重要的因素。去中心化的数据存储领域也具有巨大潜力,未来云存储市场有望达到1500亿美元。DAO和社交代币将成为购买和控制现实世界资产的重要方式,而GameFi作为数字资产在高收入游戏中的应用有望推动数字资产走向主流。衍生品市场也在不断发展壮大。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
author-avatar
鐘彦璋864175
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有