C# 3.0\3.5 新特性


索引: 


 1、自动属性 

以前

        private string lastName;
        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }

        }  

现在 

        public string LastName
        {
            get;
            set;

        } 

  C#编译器遇到上面空的get/set属性时,会自动在类中生成一个私有成员变量来保存其值。于是原先的三行代码用一行就轻松实现了。

不过有利必有弊:

比如不能在自动属性定义的属性中加逻辑判断, get/set必须成对出现等。。。

2、对象初始化器 

对象初始化器由一系列成员对象组成,其对象必须初始化,用逗号间隔,使用{}封闭。

            Person p = new Person()

            {
                FirstName = "彭",
                LastName = "飞",
                Age = 28
            }; 

            List<Person> ps = new List<Person>{

                new Person() { FirstName = "彭", LastName = "飞", Age = 28 },
                new Person() { FirstName = "张", LastName = "三", Age = 25 }
            };

除了在初始化类时设置简单的属性值外,对象初始化特性还允许我们设置更复杂的嵌套属性类型:

            Person p = new Person()
            {
                FirstName = "彭",
                LastName = "飞",
                Address = new Address()
                {
                    City = "合肥",
                    Zip = "230051"
                }

            }; 

3、集合初始化器 

集合初始化器由一系列集合对象组成,用逗号间隔,使用{}封闭。 

集合初始化器可以简化把几个对象一起添加到一个几个,编译器会自动为你做集合插入操作。

            List<int> num = new List<int>() { 0, 1, 2, 6, 7, 8, 9 }; 

            List<Person> ps = new List<Person>{

                new Person() { FirstName = "彭", LastName = "飞", Age = 28 },
                new Person() { FirstName = "张", LastName = "三", Age = 25 }

            }; 

    对象与集合初始化器要点:

    1、对象初始化器实际上利用了编译器对对象中对外可见的字段和属性进行按序赋值。

    2、对象初始化器允许只给一部分属性赋值,包括 internal 访问级别。

    3、对象初始化器可以结合构造函数一起使用,并且构造函数初始化优先于对象初始化器执行。

    4、集合初始化器会对初始化器中的元素进行按序调用 ICollection<T>.Add(T) 方法。 

    5、注意对象初始化器和集合初始化器中成员的可见性和调用顺序。

    6、对象与集合初始化器同样是一种编译时技术。

4、隐式类型变量 

使用VS2008/2010,可以声明一个变量,让编译器隐式的决定该变量的类型。 

LING就基于此功能来处理所创建的变量的。

此功能,需要使用 var 关键字:var x = 5;

使用这个语句时,编译器会使用 5 来确定该变量的类型。意味着,该语句实际应表示为:int x = 5;

.NET Framework 隐式类型变量是强类型的,在编译器第一次编译后 var 就会被确定的类型所替代的。

隐式类型变量的关键字 var 与JavaScript中的 var 相同,但意义完全不同...

JavaScript是弱类型的语言,JavaScript中变量可以变换类型,如:var s = "abcd";   s = 3;   alert(s); 

但在C#3.0中就无法改变类型,如下代码就无法编译通过:var ss = "abcd";   ss = 4;

  综上所述:在使用 .NET Framework 隐式类型变量 var 定义变量时有以下特点:

1、必须在定义时初始化。也就是必须为:var s = "abcd"; 的形式,而不能为如下形式:

var s;

s = "abcd"; 

     因为它是编译器根据上下文推断出来的,所以所有一切不能被编译器推断出来的用法都是错误。

2、var 要求是局部变量。

3、隐式类型变量 var 定义变量和 object 不同,它在效率上和使用强类型方式定义变量完全一样。

     建议:如果事先知道变量的类型,尽量使用强类型方式来声明变量。否则大量使用 var ,很难断定某个变量是什么类型。

     只在编译器可推断而人不可推断的时候才使用隐式类型局部变量,靠我们人工可推断的不建议使用。 

5、匿名类型 

匿名类型允许定义行内类型,无须显式定义类型。常和 var 配合使用来声明匿名类型。 

            var p1 = new { Id = 1, Name = "彭飞", Age = 22 };//属性也不需要申明

            var p2 = new { Id = 2, Name = "彭飞", Age = 25 }; 

    p1 = p2;  // p1、p2 结构相同,可以互相赋值 

在这里编译器会认为 p1、p2 相当于:

            public class SomeType

        {
                  public int Id { get; set; }
                  public string Name { get; set; }
                  public int Age { get; set; }
            } 

那么数组怎么定义呢?使用 “new[]” 关键字来声明数组,加上数组的初始值列表,如:

            var intArray = new[] { 2, 3, 5, 6 };
            var strArray = new[] { "Hello", "World" };
            var anonymousTypeArray = new[] 
                                    { 
                                        new{ Name = "彭飞", Age = 22 }, 
                                        new{ Name = "彭飞", Age = 25 } 

                                    }; 

    匿名类型要点:

    1、可以使用 new 关键字调用匿名初始化器创建一个匿名类型的对象。

    2、匿名类型直接继承自 System.Object

    3、 匿名类型的成员是编译器根据初始化器推断而来的一些读写属性。

6、扩展方法 

“扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。”

先上例子,以 string 为例,需要在字符串类型中加一个从字符串转为数值的功能。

以往会这样做,专门写一个方法做转换: 

        public static int StrToInt(string s)
        {
            int id;
            int.TryParse(s, out id);//这里当转换失败时返回的id为0
            return id;
        }

调用时:

            string s = "abc";

            int i = StrToInt(s); 

如是String类型有一个名为 ToInt() (从字符串转为数值)的方法,就可以直接调用: 

            string s = "abc";

            int i = s.ToInt(); 

So 创建如下类:

View Code 
    public static class EString
    {
        /// <summary>
        
/// 将字符串转换为Int
        
/// </summary>
        
/// <param name="t"></param>
        
/// <returns>当转换失败时返回0</returns>
        public static int ToInt(this string t)
        {
            int id;
            int.TryParse(t, out id);//这里当转换失败时返回的id为0
            return id;
        }

如上代码,扩展方法规定类必须是一个静态类,EString 是一个静态类,里面包含的所有方法都必须是静态方法。

MSDN这样规定扩展方法: 

      “扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。

它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。”

EString 里有一个 ToInt 的静态方法,他接收一个自身参数 this ,类型为 string ,this string 必须在方法参数的第一个位置。

即对 string 扩展一个 ToInt 方法,this 是 string 实例化后的对象。

通俗点:扩展方法跟静态类的名称无关,只需要在一个静态类里面定义一个静态方法,第一个参数必须为 this string 开头。

如果你需要对 DateTime 类型扩展方法名为 IsRange (判断是否在此时间范围内),代码如下:

View Code 
    public static class EDateTime
    {
        /// <summary>
        
/// 此时间是否在此范围内 -1:小于开始时间 0:在开始与结束时间范围内 1:已超出结束时间
        
/// </summary>
        
/// <param name="t"></param>
        
/// <param name="startTime"></param>
        
/// <param name="endTime"></param>
        
/// <returns></returns>
        public static int IsRange(this DateTime t, DateTime startTime, DateTime endTime)
        {
            if (((startTime - t).TotalSeconds > 0))
            {
                return -1;
            }

            if (((endTime - t).TotalSeconds < 0))
            {
                return 1;
            }

            return 0;
        }

  如此调用: time.IsRange(t1, t2);//判断时间time是否在t1到t2的范围内 

   谢谢。。。

原文地址:https://www.cnblogs.com/pengfei/p/2625813.html