打造轻量级的实体类数据容器

by admin on 2018年12月15日
public decimal SumAccounts(IEnumerable<Account> myAccounts) 
{      
   return myAccounts.Sum(a => a.Balance);
}

                }
            }
            this.Values = list;
            return list.Count;
        }

广阔错误#8:遗漏资源自由

 

当了,任何规则都出异。所以,有些上,尽管您的代码在编译器看来是聊问题之,然而及时正是你想使的。在这种好少见的状况下,你尽好使用
#pragma warning disable [warning id]
把吸引警告的代码包裹起来,而且只有包警告ID对应之代码。这会还只碰面抑制对应之警示,所以当有新的警告来的时候,你仍然会通晓之。.
总结

           
EntityContainer ec = new EntityContainer(q, db);
            ec.Execute(); //可以简单此行调用
            var mapUser1 = ec.Map<User>().ToList ();
            var mapGroup1=
ec.Map<Group>().ToList();


 

其他一个普遍的陷阱是好失去贯彻一个汇类型。这并无是说永远不要这样做,你得经过动要扩张.NET提供的一些于广泛利用的聚众类型来节省大量的工夫,而休是错过还过去轮子。
特别是,C#的C5 Generic Collection Library
和CLI提供了很多附加的汇聚类型,像持久化树形数据结构,基于堆的先期级列,哈希索引的数组列表,链表等及重复多。

 

C#举凡种植面向对象的强类型语言。C#每当编译和运行时犹有强类型检查,使在大部卓越的编程错误可以让尽早地觉察,而且地方一定一定精准。相相比较于这些不拘泥类型,在违规操作很老后才报生而追踪至莫名其妙错误的语言,这足以吧程序员节省成千上万日。可是,许多程序员有意依旧无意识地废了之检测的略,这导致本文中探究的片题目。

如今数据存放进去了,怎么着利用啊?为了完成通用,具体每个数据的运或者提交使用者自己失去处理吧,所以用一个寄方来拍卖:

至于本文

 

一个宽广的事例是,你改改了你的代码,并移除了对一些变量的行使,可是,你忘掉了变除该变量的扬言。程序可以非常好之周转,但是编译器会提醒有免用的变量。程序可以挺好之运行使得有些程序员不去修补警告。更有甚者,有些程序员很好之采用了Visual
Studio中“错误列表”窗口的隐藏警告的功用,很易之虽管警告过滤了,以便专注让左。不用多少长度期,就会合攒一积警告,这个警告都为“惬意”的大意了(更欠好的凡,隐藏掉了)。

假使看这样分别用简单个实体对象集合(
user和group)相比较麻烦,那么再从定义一个“用户部门”类即可:

告诫的面世是起因之。所有C#的编译错误还标志你的代码有欠缺,同样,一些警戒吗是如此。这两者之间的分别在于,对于警告的话,编译器可以以卿代码的指令工作,可是,编译器发现而的代码来一样接触小题目,很有或汇合如您的代码不克随卿的预想运行。

是因为是例子可以见见,PDF.NET的ORM框架中的实体对象查询语言–OQL,已经得以形成好复杂的查询了,包括多实体类涉查询。

然在稍情形下,有无比多之选与尚未丰富的挑三拣四同一不好,集合类型为是这般。数量众多底选项余地肯定能够保是你的做事健康运行。可是若无与伦比好如故消费有时日提前查找并问询一下集聚类型,以便采用一个顶符合你要之聚众类型。这最后会如你的次第性能再好,缩短失误的或者。

            EntityContainer ec = new EntityContainer(q, db);
            //ec.Execute();//可以略此行调用

C#凡是上微软官语言运行库(CLR)的个别言语中之同一种植。达成CLR的语言可以收益于其带来的表征,如跨语言集成、相当处理、安全性增强、部件组合的简要模型与调节以及剖析服务。作为现代底CLR语言,C#举凡应用最常见的,其用场景针对Windows桌面、移入手机和服务器环境十分繁杂、专业的支出品种。

public string GetTradeTypeID(string foundAccount,string jjdm,string type)
        {
            /*行下的询问将用如下类似的SQL:
             select distinct a.tradetype tradetypeid from wft_customerfundtrade a
                 left join wft_customerfundtradedetails b on a.tradetype =b.tradetypeid
                      where   (a.fundaccount =’1185919705′  and a.jjdm =’KF0003’)
                         and ( b.tradetype=’定投’ or b.tradetype=’基金转换的记帐’)
             * 
             */
            WFT_CustomerFundTrade trade = new WFT_CustomerFundTrade() { FundAccount = foundAccount, JJDM = jjdm };
            WFT_CustomerFundTradeDetails detail = new WFT_CustomerFundTradeDetails() { TradeType = type };
            OQLCompare cmpAll = new OQLCompare(trade, detail);

干什么不是【point
1】空?答案是,点是一个值类型,和默认值点(0,0)一样,没有空值。
即是一个十分简单和广大的缪。在C#吃许多(然而非是浑)值类型有一个【IsEmpty】属性,你可望她是不是等于默认值:

当Map方法中,可以投出任意PDF.NET实体类,或者其他由定义之POCO实体类,而且尚未映射次数限制。看到这里聪明的你也许要咨询了,下边的例子可以映射User之外的实体吗?答案是全可以!

  Point point1 = new Point(20, 30);
  Point point2 = point1;
  point2.X = 50;
  Console.WriteLine(point1.X);       // 20 (does this surprise you?)
  Console.WriteLine(point2.X);       // 50

  Pen pen1 = new Pen(Color.Black);
  Pen pen2 = pen1;
  pen2.Color = Color.Blue;
  Console.WriteLine(pen1.Color);     // Blue (or does this surprise you?)
  Console.WriteLine(pen2.Color);     // Blue

 除了足以动用 GetItemValue<T>(string fieldName)
方法来取迭代的此时此刻举办的某列数据外,也足以使 GetItemValue<T>(int
fieldIndex) 方法。

相同种植方法是失去押一下目的是怎么定义的(在Visual
Studio中,你可管光标放在对象的名字上,并坚守下F12键)

 

虽说数据库的查询操作是LINQ的一个大出众的应用,但是她同样好下叫各个可枚举的成团对象。(如:任何实现了IEnumerable接口的对象)。举例来说,要是你出一个Account类型的再三组,不要写成下面这样:

 

充显明确,倘若不对方法2回到的结果开展判定的话,最终死可能相会发出一个
NullReferenceException
的死去活来,这说不定会见现出于有些晚数的当儿,那使得问题又难追踪。相比较的话,方法1会师应声吐弃来一个
InvalidCastExceptionmaking,这样,问题之来源于就是这么些分明了。

            q.Distinct = true;

立时并表示最不用为此终结器,显式释放资源并无会晤促成中的别样一个结局。当你打开一个文件、网络端口或者数额连接时,当你不再以这多少个资源时,你该尽快的显式释放那一个资源。

先期押一个例证,大家设系统面临还存一个实体类
Group,我们采纳PDF.NET的OQL表明式写一个支撑有限独实体连接查询的语句:

对此拍卖抽象操纵集合任务,LINQ无疑是大的。无论他们是于内存的目的,数据库表,或者XML文档。在如此一个到世界中间,你免待精通底层对象。不过要我们活在一个到家世界中可能会晤带来错误。事实上,当当准的一律数量上实施时,假设该数量碰巧在一个异的格式之中相同之,LINQ语句能返不同的结果

           
EntityContainer ec = new EntityContainer(q, db);
            ec.Execute();
            var mapUser1 = ec.Map<User>().ToList ();

再增长使用了编辑器的智能感知的意义,这种似是而非就是万分有或有。

                    do
                    {
                        values = new object[fcount];
                        reader.GetValues(values);
                        list.Add(values);
                    } while (reader.Read());

  • 当于用户输入的字符串或者将字符串相比结实突显给用户时时,使用本地化的可比(CurrentCulture
    或者CurrentCultureIgnoreCase)。
  • 当用于程序设计之相比较字符串时,使用旧的较(Ordinal 或者
    OrdinalIgnoreCase)
  • InvariantCulture和InvariantCultureIgnoreCase一般并无使,除非在受限的步之下,因为本来之于普通效用又胜。倘诺和地面文化有关的可比是必要的,它应该让实施成基于时之知要另外一样栽特殊文化的较。

下面的测试例子中,User类是一个实体类,所以可以用底的方一向获取该类的实例对象集合:


下是欠模式的使示例:

以用好C#倍受的连串安全,你无限好选使用一个泛型接口,而非是采取非泛型的假说。泛型接口中之素类型是你在在宣称对象时指定的项目,而休泛型中的元素是object类型。当以一个非泛型的接口时,C#的编译器无法针对而的代码举办路检查。同样,当您以操作原生类型的集合时,使用非泛型的接口会招C#本着这一个序列举办多次的装箱(boxing)和拆箱(unboxing)操作。和行使指定了适合类型的泛型集合比较,这会带动十显然朗的属性影响。

   
可是,这么些“数据容器”依然显得相比较重量级,里面有极致多设互的分对象,为之我于PDF.NET(PWMIS数据开发框架)中定义了一个生轻量级的实业数据容器,它存储数据的规范很简单,就是一个object[][],外加一个对应的字段名称数组,其余诸如表的处女素据等消息都没存储,也就是是下程序中之3只村办对象:

  try 
  {
    myInt = int.Parse(myString);    // use myInt
  }
  catch (FormatException) 
    // use default value
  }

            var mapEntity= ec.Map<UserGroup>((e) => 
            {
                e.GroupName = ec.GetItemValue<int>(“GroupName”);
                e.ID = ec.GetItemValue<int>(“ID”);
                e.Name = ec.GetItemValue<string>(“name”);//不区分轻重缓急写
/*
//或者利用索引的艺术,但不可以不精通点OQL表明式Select方法中属性的逐一 
                e.GroupName = ec.GetItemValue<strng>(2);
                e.ID = ec.GetItemValue<int>(0);
                e.Name = ec.GetItemValue<string>(1);

像,下边演示了C#未遭开展亮类型转换的简单栽不同的办法:

        /// <summary>
        /// 执行Data里德r查询,并拿查询结果缓存
        /// </summary>
        /// <param name=”reader”>数据看器</param>
        /// <returns>结果行数</returns>
        public int Execute(IDataReader reader)
        {
            List<object[]> list = new List<object[]>();
            using (reader)
            {
                if (reader.Read())
                {
                    int fcount = reader.FieldCount;
                    fieldNames = new string[fcount];
                    object[] values = null;

当上边示例中利用using语句,你尽管好确定myFile.Dispose()方法会在文书使用了将来于当即调用,不管Read()方法暴发没出撇下大。

 

事实上我们也许曾经这样实现了之艺术,而休是提问啊使发恢宏方法。扩大方法本身就是C#的一个便宜而随便需继续、重新编译或者修改原始代码就可以叫就怀的在品种“添加”方法的措施。

        }

  public struct Point { … }     // defines a “value” type
  public class Pen { … }        // defines a “reference” type

下边的代码是事实上项目遭到之一律截代码,大家来探望完整的调用模式:

  int.Parse();     // 如果参数无法解析会抛出异常
  int.TryParse();  // 返回bool值表示解析是否成功

  IEnumerable.First();           // 如果序列为空,则抛出异常
  IEnumerable.FirstOrDefault();  // 如果序列为空则返回 null 或默认值

  

当位置的代码中,myAccounts参数的种为声称也IEnumerable<Account>,myAccounts引用了一个Sum
方法 (C# 使用类似之 “dot notation”
引用方法或者接口中的类),我们想在IEnumerable接口中定义一个Sum()方法。然而,IEnumerable没有为Sum方法提供其他引用并且唯有如下所显示之简洁定义:

OQL q=OQL.From(user)
         .InnerJoin(group) //连接Group实体
         .On(user.GroupID,group.ID)
         .Select(user.ID,user.Name,group.GroupName) //拔取指定的字段

(其余待提出的是,定义扩大方法的IEnumerable接口和Enumerable类的讳里的相似性没什么奇怪之。那种相似性只是随便的品格选用。)

 

则当时是一个百般简短的例子,在有点情形下,一个纯的LINQ语词可以自由地更迭掉你代码中一个迭代轮回(或嵌套循环)里的几十久语句。更不见之代码平日意味着来Bug的时也相会重复不见地给引入。可是,记住,在性方面可能要权衡一下。在性质分外重大之景观,尤其是您的迭代代码可以针对而的成团举办假若时,LINQ做不至,所以必然即便在当时半种办法之间比较一下特性。

   
这里发出三单重点词:轻量级实体类数量容器,还有一个潜在的重中之重词:通用。这几乎只名词中暴发啊关联为?

譬如说,请考虑下的语:

        /// <summary>
        /// 接纳自定义的映射格局,将数据容器中之数码映射到指定的接近中 
        /// </summary>
        /// <typeparam name=”TResult”>结果类型</typeparam>
        /// <param name=”fun”>处理多少的法子</param>
        /// <returns></returns>
        public IEnumerable<TResult> Map<TResult>(Func<TResult> fun) where TResult : class, new()
        {
            if (this.Values != null && this.fieldNames != null)
            {
                foreach (object[] itemValues in this.Values)
                {
                    TResult t = new TResult();
                    this.currValue = itemValues;
                    fun(t);
                    yield return t;
                }
            }
            else
            {
                throw new Exception(“EntityContainer 错误,调用该方法前请先调用Execute 方法。”);
            }
        }

而是,那并无说明 TryParse
方法重新好。某些意况下切,某些情况下则非符合。这虽然是干什么暴发个别种办法供我们选拔了。依据你的具体情形选用当的方法,并切记,作为一个开发者,相当是完全好变成你的心上人之。

 class UserGroup 
{
    int ID{get;set;}
    string Name{get;set;}
    string GroupName{get;set;}
}

一些C#的程序员甚至还不精通LINQ的是,好于非清楚之食指在日渐削减。不过还生头人误以为LINQ只所以当数据库询问中,因为LINQ的基本点字和SQL语句其实是最为像了。

*/
                return e; 
            }
            ).ToList ();

  class Program {
      static Point point1;      static Pen pen1;      static void Main(string[] args) {
          Console.WriteLine(pen1 == null);      // True
          Console.WriteLine(point1 == null);    // False (huh?)
      }
  }

 

在扩张方法的名以及接近中定义之办法的讳如出一辙,只是在法签名上生细小区其它当儿,甚至那个熟悉扩大方法的开发者也偶尔犯上边的荒唐。很多时间会面吃消费在搜寻“不有”的拼写错误上。

次第中使用 reader.GetValues(values)
方法,它不用对每列举办数据读取,所以数据读取的频率比高。

万一来一个成团指定的元素类型(如string或bit)和而方操作的同,你最好优先挑选下它。当指定相应之要素类型时,这种集的频率又强。

 

decimal total = 0;  
foreach (Account account in myAccounts) 
{    
     if (account.Status == "active") 
     {
        total += account.Balance;
     }
}

 

普遍错误 #1: 把援当做值来用,或者转

    /// <summary>
    /// 实体数据容器
    /// </summary>
    public class EntityContainer
    {
        private string[] fieldNames;
        private List<object[]> Values;
        private object[] currValue;

答案是,当以LINQ语句被的基础对象还引用到SQL表中之多少(如与于此事例中,在实体框架为DbSet的对象的景下),该语句被移成为一个T-SQL语句。然后照的T-SQL的条条框框,而非是C#的平整,所以于上述状况下之较了是匪区分轻重缓急写的。

   
一般的话,操作实体类往往伴随在一个实体类集合,而这一个聚集就是实体类的容器,在此处自己以“容器”视作一个比集合更普遍的概念,例如Entity
Framework做了一个重量级的器皿ObjectContext,用于与当目的(这多少个目的呢
EDM 中定义的实体类型的实例)的数开展交互。

public bool Equals(string value);  



public bool Equals(string value, StringComparison comparisonType);

实体容器接收一个DataReader对象,将中间的多少读入Values
数组,下边是应和的措施代码:

#5日常表现错:在LINQ语句之中无考虑底层对象

下就是足以投出点儿个实体集合了:

C#供了大量之聚众类型的目标,上边仅排有了间的等同部分:

点的写法没有LINQ那么到,人家LINQ是近水楼台先得月,MS自家的胚芽,可以凭借“编译器语法糖”来描写起赏心悦目的LINQ程序,但咱的这实现自常理上说好轻快,在广大地下的ORM框架中,真正辅助了实体类的多表连接查询!


 

若果达到所示,在C#中,struct关键字是为此来定义一个值类型,而class关键字是由此来定义引用类型的。
对于那个有C++编程背景人来说,假如被C++和C#中间某些类似的关键字作混,可能会师针对上述这种行为感到老吃惊。

             //具体代码略

想像一下,该目标某之账号会生出啊。状态卓越“Active”(注意大写A)?

            OQL q = OQL.From(trade)
                .LeftJoin(detail).On(trade.TradeType, detail.TradeTypeId)
                .Select(trade.TradeType)
                .Where(
                        (cmpAll.Comparer(trade.FundAccount) & cmpAll.Comparer(trade.JJDM)) &
                        (cmpAll.Comparer(detail.TradeType) | cmpAll.Comparer(detail.TradeType, “=”, “基金转换的记帐”))
                )
                .END;

C#举凡一样流派强大的同时颇利索的言语,它发那些体制同语言专业来家喻户晓的增强而的生产力。和其它语言同样,假诺对它们能力的刺探有限,这充足可能谋面吃你带阻碍,而非是补。正使一词谚语所说的那么“knowing
enough to be
dangerous”(译者注:意思是自以为已经了解丰裕了,可以举办某事了,但实则不是)。

   
实体类与容器没有早晚关系,例如DataSet也是一个器皿,它存储并操作DataTable,而DataTable也得以看作是各样单元格数据的容器…

卿如若这么形容:

    }

CLR
托管环境去了废品回收器的角色,所以您莫需显式释放已创造对象所占的内存。事实上,你啊未可以显式释放。C#屡遭没有同C++
delete对应之运算符或者和C语言中free()函数对应的法子。但立时并无意味着你可忽略所有的使过的对象。许多目的类型封装了许多另外项目标系统资源(例如,磁盘文件,数据连接,网络端口等等)。保持这些资源以状态会重耗尽系统的资源,削弱性能并且最后促成程序出错。

           
EntityContainer ec = new EntityContainer(q, db);
            ec.Execute();
            var mapUser2= ec.Map<User>((e) => 
            {
                e.Age = ec.GetItemValue<int>(“Age”);
                e.ID = ec.GetItemValue<int>(“ID”);
                e.Name = ec.GetItemValue<string>(“name”);//不分轻重缓急写
                return e; 
            }
            ).ToList ();

极致安全之行是接二连三为Equals方法提供一个comparisonType的参数。

 

倘无是如此:

 

Array,ArrayList,BitArray,BitVector32,Dictionary<K,V>,HashTable,HybridDictionary,List<T>,NameValueCollection,OrderedDictionary,Queue, Queue<T>,SortedList,Stack, Stack<T>,StringCollection,StringDictionary.

此外,还提供了一个以数据映射到PDF.NET实体类的章程,下面是方的定义:

  public decimal SumAccounts(IEnumerable<Account> myAccounts) 
  {
      return Enumerable.Sum(myAccounts, a => a.Balance);
  }

事后,能够像下这样来以数据:

本文描述了10个 C# 程序员常犯的左,或该幸免的陷阱。

                    for (int i = 0; i < fcount; i++)
                        fieldNames[i] = reader.GetName(i);


        /// <summary>
        /// 将数据从容器中映射到实体中
        /// </summary>
        /// <typeparam name=”T”></typeparam>
        /// <returns></returns>
        public IEnumerable<T> Map<T>() where T : EntityBase{

略知一二了立或多或少,我们雅观看下面介绍的sumAccounts方法能因下边的主意实现:

            EntityContainer container = new EntityContainer(q);
            var result = container.Map<WFT_CustomerFundTrade>().ToList();
            if (result.Count == 0)
                return “”;
            else
                return result[0].TradeType;
}


 

此外,就算你懂要对方法2的回来值举办判断,虽然你意识价值吗空,接下你碰面怎么开?在斯艺术中告知错误合适与否?假设类型转换败北了你还爆发其他的法子去尝尝也?假如无的话,那么抛出这多少个可怜是绝无仅有正确的取舍,并且非凡的废来点离该发点更为走近越好。

 

固然所有C#的类似中都定义了析构方法,不过销毁对象(C#面临呢称为终结器)可能在的题目是若无确定其以时段给调用。他们以以后一个勿确定的工夫吃垃圾回收器调用(一个异步的线程,此举或引发额外的产出)。试图制止这种由垃圾回收器中GC.Collect()方法所施加的强制限制并非同一栽好之编程实践,因为可能当渣回收线程试图回收适宜回收的目的时,在不可预知的日内造成线程阻塞。

有关OQL的多实体连接查询才于PDF.NET框架V4.1未来版本襄助,该成效作为框架的相同宗重点力量扩展,已经以经贸类型面临初阶运用,感兴趣之爱人可齐探讨。

在C#未遭爆发众多道来比字符串。

今昔,你的代码中来矣一个重的失实(可是编译器只是出口了一个告诫,其原因既表达了),这会浪费你大量之时刻错开找寻那错,具体情状由你的程序复杂程度决定。假设您平发轫便留心到了这一个警示,你唯有需要5分钟就足以改掉,从而避免那题目。

  if (int.TryParse(myString, out myInt)) 
  {
      // use myInt
  }
  else 
  {    
      // use default value
  }

只是,如若您忽略掉这同样接近的告诫,类似于下是例子迟早会起于您的代码中。

在C#受到,值得类型不可知吧空。遵照定义,值的类型值,甚至开首化变量的值类型必须发一个价。这虽是所谓的欠类型的默认值。这一般会招以下,出人意料的结果平常,检查一个变量是否不最先化:

 namespace System.Linq 
 {
    public static class Enumerable 
    {      ...
      // the reference here to “this IEnumerable<TSource> source” is
      // the magic sauce that provides access to the extension method Sum
      public static decimal Sum<TSource>(this IEnumerable<TSource> source,Func<TSource, decimal> selector);      ...
    }
 }

周边的错误#2:误会未起先化变量的默认值

上边是有主干的点拨原则:

扩大方法的分明特点是首先个形参前的this修饰符。这就是是编译器知道她是一个扩张方法的“奥妙”。它所修饰的参数的花色(那一个事例中的IEnumerable)表达这仿佛仍然接口将显示实现了之点子。

另外,对Equals
方法吧,字符串也常见提供了Compare方法,可以供字符串的相对顺序音讯假若不仅测试是否当。那些法子好非常好适用于<,
<=, >和>= 运算符,对上述议论同样适用。

下带来comparisonType的Equals方法去于字符串,不仅会如你的代码更清,还会晤要您错过考虑清楚要为此哪类档次去比字符串。那种办法异常值得你去用,因为即便以西班牙语受到,按顺序举行的可比和本语言区域拓展的比中并没尽多之分,可是于另外的局部语种可能会晤生丰盛可怜之异。假使您忽视了这种可能性,无疑是吗您自己于未来底征途及抠了不少“坑”。举例来说:

来源:http://www.oschina.net/translate/top-10-mistakes-that-c-sharp-programmers-make

诚如情状下,即便LINQ是一个有益的跟平等的点子来询问对象的汇集,在切切实实中君还亟需领会乃的口舌是否会见被翻译成什么,来确保您的代码的行拿使预期运行。

只要您所展现,就算Point和Pen对象的创办格局相同,可是当一个初的X的坐标值被分配到point2平常,
point1的值保持无转移
。而当一个新的color值被分配到pen2,pen1也随后变动。由此,我们可估计point1和point2每个都饱含自己之Point对象的副本,而pen1和pen2引用了和一个Pen对象
。假若无这测试,大家怎么能知道这规律?

在C#
3.0中,LINQ的引入改变了俺们往本着聚集对象的查询和修改操作。从这以后,你应当据此LINQ去操作集合,而无是经迭代底点子。

  using (FileStream myFile = File.OpenRead("foo.txt")) {
    myFile.Read(buffer, 0, 100);
  }

即便如此发出成百上千程序员使用==操作符来比字符串,然而这种措施其实是不过无推荐以的。重要原因是由于这种形式无于代码中显式地指定使用啊序列型去于字符串。
相反,在C#面临判断字符串是否当最好用Equals方法:

广大错误 #10: 累积编译器警告而非处理

关于C#

  string s = "strasse";

  // outputs False:
  Console.WriteLine(s == "stra&szlig;e");
  Console.WriteLine(s.Equals("stra&szlig;e"));
  Console.WriteLine(s.Equals("stra&szlig;e", StringComparison.Ordinal));
  Console.WriteLine(s.Equals("Stra&szlig;e", StringComparison.CurrentCulture));        
  Console.WriteLine(s.Equals("stra&szlig;e", StringComparison.OrdinalIgnoreCase));

  // outputs True:
  Console.WriteLine(s.Equals("stra&szlig;e", StringComparison.CurrentCulture));
  Console.WriteLine(s.Equals("Stra&szlig;e", StringComparison.CurrentCultureIgnoreCase));

本,你吧足以形容你自己之恢宏方法。可是要意识及即使扩张方法看起来与此外实例方法一致给调用,但迅即实在只是幻觉。事实上,扩充方法无克看所推广展类的私房和护卫成员,所以其无法于作传统延续的替代品。

吓吧,假使myaccout是Dbset的靶子。(默认设置了不同组别轻重缓急写的配备),where表达式仍会配合该因素。然则,如若myaccout是以内存阵列之中,那么它以不般配,因而用出不同之终究的结果。

即使本文啄磨的多数错是针对性 C# 的,有些错误和其他为 CLR
为目标的言语,或者以了 Framework Class Library (FCL) 的语言也连带。


大规模错误 #9: 回避非常

  // 方法 1:
  // 如果 account 不能转换成 SavingAccount 会抛出异常
  SavingsAccount savingsAccount = (SavingsAccount)account;

  // 方法 2:
  // 如果不能转换,则不会抛出异常,相反,它会返回 null
  SavingsAccount savingsAccount = account as SavingsAccount;
Console.WriteLine(point1.IsEmpty);        // True
 public interface IEnumerable<out T> : IEnumerable 
 {
      IEnumerator<T> GetEnumerator();
 }
  decimal total = (from account in myAccounts
               where account.Status == "active"
               select account.Balance).Sum();

C#每当运行时也会合强制举办项目检查。相对于诸如C++那样会为左的类型转换赋一个随机值的语言来说,C#立刻可假若你再次快之找到出错的职位。但是,程序员再同糟糕无视了C#的即无异风味。由于C#供了少数栽类型检查的办法,一种植会扔来卓殊,而另一样种则免会晤,这分外可能会合使她们少进那“坑”里。有些程序员倾向于回避很是,并且认为无写
try/catch 语句可以节省一些代码。

大规模错误 #6:对扩充方法感到疑惑或叫它的花样欺

若你想假如靠的一言一行会盖值类型和援类型而异,举例来说,倘若你想管一个目的作为参数传给一个道,并在这么些法中改者目的的状态。你必假若包您当拍卖对的项目对象。

一经当一个代码段被开创并释放一个靶,却遗忘调用Dispose()方法,这是不行原谅的,由此C#供了using语句以管教无代码以什么的点子退出,Dispose()方法还会师给调用(不管是这一个,return语句,或者略的代码段竣工)。这些using和前提到的于文书最先用来引入名字空间的一致。它暴发此外一个过多C#开发者都无发现的,完全无系的目标,也就是管代码退出时,对象的Dispose()方法被调用:

大面积错误 #7: 对手头上的天职选拔不当的汇类型

推个有血有肉的例证,某些状况下当好来时,你闹另外一个可选的计(如,默认值),那么,选择不废来深的艺术是一个相比较好的挑。在这种气象下,你最好相仿上边这样勾画:

C++
和此外众多语言的程序员,习惯了吃变量赋值的当儿,要么赋单纯的价,要么是并存对象的援。但是,在C#
中,是价值如故引用,是由写这目的的程序员决定的,而非是实例化对象并赋值的程序员决定的。这频繁会坑至
C# 的新手程序员。

普遍误区 #4: 使用迭代式 (而无是讲明式)的喻词去操作集合

对C#编译器来说,扩充方法是独“语法糖”,使我们会拿代码写得重显明,更易于维护(多数情状下)。分明,前提是您懂她的用法,否则,它晤面较容易吃人口迷惑,尤其是相同开始。

熟悉C#的片段要之细小之远在,像本文中所干的这么些(但未杀那一个),可以援助我们重好的错过下语言,从而制止有宽广的钩。

多少程序员认为“非凡有害”,所以他们自不过然的看无撤销来相当的主次显得尤其“高大上”。即使当某些情况下,这种理念是无可非议的,然则这种看法并无适用于拥有的状态。

首先单Equals方法(没有comparisonType这参数)和运==操作符的结果是如出一辙的,但利益是,它显式的指明了比类型。它谋面坚守梯次逐字节的去比字符串。在广大气象下,这多亏你所希望之可比类型,尤其是当于有通过编程设置的字符串,像文件称,环境变量,属性等。在这个情状下,只要坚守梯次逐字节的于就好了。使用不带comparisonType参数的Equals方法开展较的绝无仅有欠好的地点在于这么些读而程序代码的人可能未晓乃的可比类型是什么。

资源泄露几乎在享有的条件受到都会晤掀起关注。可是,C#提供了平等种健康的机制而资源的使变得简单。假若创立利用,可以大大缩短泄暴露现的机率。NET
framework定义了一个IDisposable接口,仅出于一个Dispose()构成。任何实现IDisposable的接口的目标都会面当靶生命周期停止调用Dispose()方法。调用结果肯定而决定性的放飞占用的资源。

而是Sum方法应该定义及何处?C#大凡强类型的言语,由此而Sum方法的援是无济于事的,C#编译器会对这报错。我们明白其必须有,然则当以乌也?另外,LINQ提供的供应查询和集结果具有方以哪定义也?

decimal total=(from accout in myaccouts
    where accout.status=='active'
    select accout.Balance).sum();

扩充方法通过当文书起始添加using
[namespace];引入到效能域。你要精通您若物色的扩张方法所在的讳空间。假设你明白你要摸的是啊,这一点特别爱。


选取扩充方法确实发生优势,但为会面于那一个对她不领会或认识不得法的开发者胸口痛,浪费时间。尤其是以圈以线示例代码,或者其他已经写好的代码的时节。当这多少个代码来编译错误(因为其调用了这么些彰着尚无当吃调用类型中定义的主意),一般的赞同是考虑代码是否接纳为所引用类库的外版本,甚至是殊之类库。很多年华会受消费在搜寻新本子,或者让认为“丢失”的类库上。

  class Account 
  {

      int myId;      
      int Id;   // 编译器已经警告过了,但是你不听

      // Constructor
      {          
         this.myId = Id;     // OOPS!
      }

  }

假设你莫亮堂你正使用的目的是否是值类型或引用类型,你恐怕碰面碰到有惊喜。例如:

这荒唐并无是C#所特有的,但是以C#倍受这种情景却比多,尤其是从C#编译器弃用了严刻的类型检查之后。

广阔错误 #3: 使用无合适或未指定的艺术较字符串

定义在System.Linq.Enumerable类中的static方法(叫做“extension method”)

当C#编译器碰着一个靶的实例调用了一个措施,并且她于斯目的的类吃找找不顶万分格局,它便会尝试在效率域中负有的扩展方法里找一个匹配所要求的近乎与道签名的。假设找到了,它就是拿实例的援当做第一个参数传被这多少个扩展方法,然后如暴发任何参数的言语,再把其依次传入扩张方法。(即便C#编译器没有于功用域中找到相应的恢弘方法,它相会抛措。)


如先前关系的,LINQ状态依赖让IEnumerable接口的贯彻目标,比如,下边的简短函数会探究帐户汇中之帐户余额:

顶一会,在大家事先研究了之字符串相比中, 我们看见 ==
操作符扮演的角色就是粗略的较. 所以,为啥当斯规则下, ==
表现出底是此外的一个样式呢 ?

牢记,假诺你细心看的口舌,你碰面发觉,C#编译器给了而多多关于您程序健壮性的灵光之新闻。不要忽视警告。你只需要花费几秒钟的日虽足以修复它们,当出现的时刻尽管夺修复它,这好为而节省成千上万时日。试着吗自己塑造同样种植“洁癖”,让Visual
Studio 的“错误窗口”一直亮“0破绽百出,
0警告”,一旦出现警示便感到不舒服,然后就把警告修复掉。

在C#倍受,用增添方法换得越来越流行。除了LINQ,在其它四只来源微软今受周边利用的类库Unity
Application Block和Web API
framework中,也采纳了扩充方法,而且还有不少其他的。框架进一步新,用扩大方法的可能越怪。

脚的例证演示了其它同组大的点子,一种会弃来很,而另一样栽则不会晤:


答案是Sum并无以IEnumerable接口内定义,而是一个

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图