C#新手常犯的错误汇总

本文所述为C#新手常犯的错误,但是实际上很多有经验的程序员也经常犯这些错误,对此特别整理了一下,供大家参考。具体如下:

1、遍历List的错误,比如如下代码:

List<String> strList =newList<String>
for(int i =0; i<strList.Count; i++)
{
  strList.RemoveAt(i);
}

这段代码看上去是删除了所有元素,实际上每次调用RemoveAt方法会导致List元素索引重排,最后导致元素没有完全删除。
可以改成:

List<String> strList =newList<String>
for(int i =0; i<strList.Count; i++)
{
  strList.RemoveAt(i);
  i-=1;
}

这样就可以完全删除List中的元素。

2、关于C#常量的错误

比如你写了一个类库,在里面定义了如下常量:

public const String str="First Version";

并且在另一个程序里引用了这个类库,如果你修改了这个类库中的常量,发布了一个新的版本,那么再运行之前的程序,你会发现常量还是原来的常量,并没有改变。这是因为C#在编译的时候,常量直接作为元数据嵌入,解决方法是重新编译整个解决方案或者使用属性而不是直接访问常量。

3、当把值类型装箱后,如果拆箱只能拆成原来装箱前的类型,比如:

Int32 a=3;
Object obj=new object();
//这里装箱成功,不会失败
obj=i;
//拆箱一定会失败
Int64 b=(Int64)obj;

可以像这样操作:

Int64 b =(Int64)(Int32)obj;

就能完成转型

4、重载==运算符的错误:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UseOperator
{
  class Program
  {
    static void Main(string[] args)
    {
      Test t1 = new Test();
      t1.MyFun();
      Console.ReadLine();
    }
  }
  class Test
  {
    public void MyFun()
    {
      Test t = new Test();
      if (t == null)
      {
        Console.WriteLine("t为空!");
      }
      else
      {
        Console.WriteLine("t不为空!");
      }
    }
    //存在BUG的重载运算法
    public static bool operator ==(Test t1, Test t2)
    {
      return t2.Equals(t1);
    }
    public static bool operator !=(Test t1, Test t2)
    {
      return !(t1 == t2);
    }
    //覆盖HashCode
    public override int GetHashCode()
    {
      return base.GetHashCode();
    }
    public override bool Equals(object obj)
    {
      return base.Equals(obj);
    }
  }
}

这里的问题在于MyFun中会把NULL传递进==运算符函数,导致运行的时候报错,正确的做法是:

public static bool operator ==(Test t1, Test t2)
{
  if ((t2 as object) == null)
  {
    return (t1 as object) == null;
  }
  else
  {
    return t2.Equals(t1);
  }
}

5、C#中调用结构的属性或者方法必须用new来声明结构变量,否则会出错。

6、如果使用了params使用多个参数,必须判断参数是否为空,否则程序会有隐藏的BUG。

7、静态成员在创建第一个实例的时候就会初始化,而且只被初始化一次,不要乱用静态成员。

8、如果使用ref Object类型参数接受String类型会出错,这是因为C#要求参数必须使用正确的类型,不加ref是可以的,如果一定要使用ref Object接受String类型参数,可以先转型成Object,再引用传递。

9、类的构造函数中永远不要调用虚方法,比如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FransferVirtualFunction
{
  class Program
  {
    static void Main(string[] args)
    {
      try
      {
        Child ch = new Child();
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
      Console.Read();

    }
  }
  public class Ref
  {
    public string Str = "这是Ref类的一个成员";
  }
  public class Parent
  {
    protected Ref my;
    public Parent()
    {
      my = new Ref();
      //构造方法中调用了虚方法
      Console.WriteLine(GetString());
    }
    //虚方法
    public virtual string GetString()
    {
      return my.Str;    //使用了内部成员
    }
  }
  public class Child : Parent
  {
    private Ref my2;
    public Child()
      : base()
    {
      my2 = new Ref();
    }
    //重写虚方法
    public override string GetString()
    {
      return my2.Str;    //使用了内部成员
    }
  }
}

这里在执行基类的构造函数的时候会执行到派生类的虚方法GetString(),在获取my2.Str的时候抛出异常,因为此时派生类对象还没有被构造。

10、在C#和SQL Server通信时要注意NULL的含义,在SQL Server里面这个值代表1900-1-1。SQL Server的空值可以使用DBNull来表示。

暂时就是这么多了,注意到以上10点可以在编程的时候减少大量BUG。

补充:

1、Math 三角函数 其中的参数为 弧度值,而非角度值。

2、WinForm 中的由相对路径引发的bug:具体可以参考WinForm相对路径的陷阱。

3、使用 xml, json 等序列化后的数据格式传递数据时,如果传递的数据为数值型类型,解析时,最好先将其转为string 然后 tryParse 成相应类型。

至于原因:如上的第三点、是装箱和拆箱的问题。

相信本文所述对大家C#程序设计可以带来很大的帮助。

(0)

相关推荐

  • 探秘C# 6.0 的新特性

    C# 6.0 中的新特性 我们可以对这些新特性一个一个的进行讨论,而首先要列出 C# 6.0 中这些特性的一个清单 自动的属性初始化器 Auto Property Initializer 主构造器 Primary Consturctor 字典初始化器 Dictionary Initializer 声明表达式 Declaration Expression 静态的Using Static Using catch 块中的 await 异常过滤器 Exception Filter 用于检查NULL值的条

  • C# XML操作 代码大全(读XML,写XML,更新,删除节点,与dataset结合等)第1/2页

    已知有一个XML文件(bookstore.xml)如下: Corets, Eva 5.95 1.插入节点 往节点中插入一个节点: 复制代码 代码如下: XmlDocument xmlDoc=new XmlDocument(); xmlDoc.Load("bookstore.xml"); XmlNode root=xmlDoc.SelectSingleNode("bookstore");//查找 XmlElement xe1=xmlDoc.CreateElement(

  • asp.net(c#)程序版本升级更新的实现代码

    直接上代码: 复制代码 代码如下: using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.IO; using System.Net; using System.Xml; namespace Update {     /// <summary>     /// 更新完成触发的事件     /// </summary>     pu

  • VS2015中C#版本6.0的新特性 你需要知道

    本文列出个人感觉比较有用的几个新功能,供大家参考,具体内容如下  注意:这些新特性只能用于VS2015及更高版本,无法在VS2013.VS2010等低版本中使用.当然,如果你不喜欢这些新的特性,仍然可以继续使用原来的用法(所以说它是新的语法糖).  1.自动属性初始化的改进(有用)  原来的用法(声明时无法同时初始化),例如: class MyClass { public int Age { get; set; } public string Name { get; set; } public

  • 深入C# 4.0 新特性dynamic、可选参数、命名参数的详细介绍

    1.dynamic ExpandoObject熟悉js的朋友都知道js可以这么写 : 复制代码 代码如下: var t = new Object(); t.Abc = 'something'; t.Value = 243; 现在这个js动态语言的特性,我们也可以在c#中使用了,前提是将一个变量声明为ExpandoObject类型.如下例: 复制代码 代码如下: static void Main(string[] args) { dynamic t = new ExpandoObject(); t

  • C#6.0中10大新特性的应用和总结

    微软于2015年7月21日发布了Visual Studio 2015, .NET 2015, .NET Framework 4.6, ASP.NET 4.6, Azure SDK 2.7 for .NET, C# 6.0, F# 4.0, TypeScript 1.5, Visual Studio Android 模拟器 等重量级开发产品. 由于项目升级到了.NetFramework 4.6.1,开发工具转向了VS2015,趁机尝试下C#6.0.结果网上的教程不进人意,许久都没有更新,只好自己做

  • C# 7.0 新特性1之基于Tuple的“多”返回值方法

    原文链接:http://www.cnblogs.com/ylvict/p/5573094.html 回顾  首先,提出一个问题,C#中,如何使一个方法可返回"多个"返回值?  我们先来回顾一下C#6.0 及更早版本的做法.   在C#中,通常我们有以下4种方式使一个方法返回多条数据. •使用 KeyValue 组合 • static void Main(string[] args) { int int1 = 15; int int2 = 25; var result = Add_Mul

  • C#4.0新特性之协变与逆变实例分析

    本文实例讲述了C#4.0新特性的协变与逆变,有助于大家进一步掌握C#4.0程序设计.具体分析如下: 一.C#3.0以前的协变与逆变 如果你是第一次听说这个两个词,别担心,他们其实很常见.C#4.0中的协变与逆变(Covariance and contravariance)有了进一步的完善,主要是两种运行时的(隐式)泛型类型参数转换.简单来讲,所谓协变(Covariance)是指把类型从"小"升到"大",比如从子类升级到父类:逆变则是指从"大"变到

  • C#利用子线程刷新主线程分享教程

    要求:如下图,使用线程操作 1.实时显示当前时间 2.输入加数和被加数,自动出现结果  分析:两个问题解决的方式一致,使用子线程进行时间操作和加法操作,然后刷新主线程的控件显示结果 复制代码 代码如下: using System; using System.Threading; using System.Windows.Forms; namespace WinThread { public partial class frmMain : Form { public frmMain() { Ini

  • C#新手常犯的错误汇总

    本文所述为C#新手常犯的错误,但是实际上很多有经验的程序员也经常犯这些错误,对此特别整理了一下,供大家参考.具体如下: 1.遍历List的错误,比如如下代码: List<String> strList =newList<String> for(int i =0; i<strList.Count; i++) { strList.RemoveAt(i); } 这段代码看上去是删除了所有元素,实际上每次调用RemoveAt方法会导致List元素索引重排,最后导致元素没有完全删除.

  • C++中新手容易犯的十种编程错误汇总

    目录 前言 1.有些关键字在cpp文件中多写了 2.函数参数的默认值写到函数实现中了 3.在编写类的时候,在类的结尾处忘记添加";"分号了 4.只添加了函数声明,没有函数实现 5.cpp文件忘记添加到工程中,导致没有生成供链接使用的obj文件 6.函数中返回了一个局部变量的地址或者引用 7.忘记将父类中的接口声明virtual函数,导致多态没有生效 8.该使用双指针的地方,却使用了单指针 9.发布exe程序时,忘记将exe依赖的C运行时库和MFC库带上 10.应该使用深拷贝,却使用了浅

  • Java程序员常犯的五个错误

    下面针对每一个错误用文字说明结合代码详解的方式展示给大家,具体内容如下: 1. Null 的过度使用 避免过度使用 null 值是一个最佳实践.例如,更好的做法是让方法返回空的 array 或者 collection 而不是 null 值,因为这样可以防止程序抛出 NullPointerException.下面代码片段会从另一个方法获得一个集合: List<String> accountIds = person.getAccountIds(); for (String accountId :

  • Java开发人员最常犯的10个错误

    这个列表总结了10个Java开发人员最常犯的错误. Array转ArrayList 当需要把Array转成ArrayList的时候,开发人员经常这样做: List<String> list = Arrays.asList(arr); Arrays.asList()会返回一个ArrayList,但是要特别注意,这个ArrayList是Arrays类的静态内部类,并不是java.util.ArrayList类.java.util.Arrays.ArrayList类实现了set(), get(),c

  • 关于mysql调用新手们常犯的11个错误总结

    前言 大家可能经常收到安全部门的警告邮件,SQL注入,XSS攻击漏洞等等,偶尔还被黑客挂了小马,郁闷不?还有数据库执行太慢(根据经验基本是没有正确使用索引导致) ,下面就跟着小编来一起看看MYSQL新手们常犯的11个错误吧. 1.使用MyISAM而不是InnoDB MySQL有很多的数据库引擎,单一般也就用MyISAM和InnoDB. MyISAM是默认使用的.但是除非你是建立一个非常简单的数据库或者只是实验性的,那么到大多数时候这个选择是错误的.MyISAM不支持外键的 约束,这是保证数据完整

  • 手写TypeScript 时很多人常犯的几个错误

    目录 前言 1.没有使用严格模式 我们为什么要使用严格模式? 2. 使用 || 确定默认值 那它应该是什么样子的呢? 3.使用any作为类型 为什么要这么做呢? 为什么不能用any? 4. val 作为 SomeType 强制告诉编译器它无法推断的类型. 这就是类型守卫的用途. 5. any在测试用例中的表现 在编写测试时 6. 可选属性 将属性定义为有时存在,有时不存在的可选属性. 清楚地表达,模型哪些组合存在,哪些不存在. 7. 使用一个字母作为泛型参数 用一个字母给作为名称,比如常用的T作

  • Python程序员开发中常犯的10个错误

    Python是一门简单易学的编程语言,语法简洁而清晰,并且拥有丰富和强大的类库.与其它大多数程序设计语言使用大括号不一样 ,它使用缩进来定义语句块. 在平时的工作中,Python开发者很容易犯一些小错误,这些错误都很容易避免,本文总结了Python开发者最常犯的10个错误,一起来看下,不知你中枪了没有. 1.滥用表达式作为函数参数默认值 Python允许开发者指定一个默认值给函数参数,虽然这是该语言的一个特征,但当参数可变时,很容易导致混乱,例如,下面这段函数定义: 复制代码 代码如下: >>

  • Python新手入门最容易犯的错误总结

    前言 Python 以其简单易懂的语法格式与其它语言形成鲜明对比,初学者遇到最多的问题就是不按照 Python 的规则来写,即便是有编程经验的程序员,也容易按照固有的思维和语法格式来写 Python 代码,之前小编给大家分享过了一篇<Python新手们容易犯的几个错误总结>,但总结的不够全面,最近看到有一个外国小伙总结了一些大家常犯的错误,16 Common Python Runtime Errors Beginners Find,索性我把他翻译过来并在原来的基础补充了我的一些理解,希望可以让

  • Python开发的十个小贴士和技巧及长常犯错误

    下面是十个Python中很有用的贴士和技巧.其中一些是初学这门语言常常会犯的错误. 注意:假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子:[2, 4, 6, 8, 10] 大多初学者,根据之前语言的经验会大概这样来做 bag = [1, 2, 3, 4, 5] for i in range(len(bag)): bag[i] = bag[i] * 2 但是有更好的方法: bag = [

  • 十个Python程序员易犯的错误

    常见错误1:错误地将表达式作为函数的默认参数 在Python中,我们可以为函数的某个参数设置默认值,使该参数成为可选参数.虽然这是一个很好的语言特性,但是当默认值是可变类型时,也会导致一些令人困惑的情况.我们来看看下面这个Python函数定义: >>> def foo(bar=[]): # bar是可选参数,如果没有提供bar的值,则默认为[], ... bar.append("baz") # 但是稍后我们会看到这行代码会出现问题. ... return bar Py

随机推荐