Fire my passion

Anything with my most passion……
C# 3.0的新特性
C# 3.0的新特性

个人感觉所有的新特性都是围绕LINQ的,所以LINQ应该是今后的重头戏
还需好好好钻研

自动化属性
对象初始化器
Lambda表达式
本地类型推断
扩展方法
匿名类
查询表达式

一、本地类型推断
使用var关键字定义变量而不是特定的类型关键字

var a = 2;       // a is declared as int
object b = 2;    // Boxing an int into an object
int c = a;       // No cast, no unboxing
int d = (int) b; // Cast is required, an unboxing is done

当使用var定义变量时,编译器常常通过初始化变量表达式
var是定义匿名类变量的唯一的方法
var变量不能定义成员变量和参数变量类型
如: 以下四种方式是不可以的
class VarDemo {
    // invalid token 'var' in class, struct or interface member declaration
    var k =0;

    // type expected in parameter list
    public void InvalidUseParameter( var x ){}

    // type expected in result type declaration
    public var InvalidUseResult() {
        return 2;
    }
    public void InvalidUseLocal() {
        var x;          // Syntax error, '=' expected
        var y = null;   // Cannot infer local variable type from 'null'
    }
   // …
}

二、Lambda 表达式

一种更加简明的方式定义匿名方法
举个例子:
public class AggDelegate {
    public List<int> Values;
    delegate T Func<T>( T a, T b );

    static T Aggregate<T>( List<T> l, Func<T> f ) {
        T result = default(T);
        bool firstLoop = true;
        foreach( T value in l ) {
            if (firstLoop) {
                result = value;
                firstLoop = false;
            }
            else {
                result = f( result, value );
            }
        }
        return result;
    }

    public static void Demo() {
        AggDelegate l = new AggDelegate();
        int sum;

使用匿名方法:

        sum = Aggregate(
                l.Values,
                delegate( int a, int b ) { return a + b; }
            );
        Console.WriteLine( "Sum = {0}", sum );
    }

    // …
}

使用Lambda表达式:
sum = Aggregate(
        l.Values,
        ( int a, int b ) => { return a + b; }
    );

sum = Aggregate(
        l.Values,
        ( a, b ) => { return a + b; }
    );

sum = Aggregate(
        l.Values,
        ( a, b ) => a + b
    );

int sum = 0;
sum = AggregateSingle(
          l.Values,
          ( x ) => sum += x
       );
当lambda表达式中的参数只有一个时,如上所示
则可以将参数两边的括号去掉

int sum = 0;
sum = AggregateSingle(
          l.Values,
          x => sum += x
       );

如果没有参数则括号必须写
( int a, int b ) => { return a + b; } // Explicitly typed, statement body
( int a, int b ) => a + b;            // Explicitly typed, expression body
( a, b ) => { return a + b; }         // Implicitly typed, statement body
( a, b ) => a + b                     // Implicitly typed, expression body
( x ) => sum += x                     // Single parameter with parentheses
x => sum += x                         // Single parameter no parentheses
() => sum + 1                         // No parameters

Predicate 和 Projection
这两个名称是指Lambda表达式不同用途的叫法
Predicate:一个bool表达式
( age ) => age > 21

Projection:返回和唯一的参数不同类型的值
( s ) => s.Length

一个Predicate的例子
public static void Demo() {
    string[] names = { "Marco", "Paolo", "Tom" };
    Display( names, s => s.Length > 4 );
}

public static void Display<T>( T[] names, Func<T, bool> filter ){
    foreach( T s in names) {
        if (filter( s )) Console.WriteLine( s );
    }
}

一个Lambda表达式也可以分配给以下委托类型的变量
public delegate T Func< T >();
public delegate T Func< A0, T >( A0 arg0 );
public delegate T Func<A0, A1, T> ( A0 arg0, A1 arg1 );
public delegate T Func<A0, A1, A2, T >( A0 arg0, A1 arg1, A2 arg2 );
public delegate T Func<A0, A1, A3, T> ( A0 arg0, A1 arg1, A2 arg2, A3 arg3 );

上面这些委托已经存在于System.Linq命名空间中
但是如果将一个lambda表达式转换成一个Expression Tree,编译器将在执行时把lambda表达式转换成二进制可执

行代码

Expression Tree是System.Linq.Expressions.Expression<T>类的实例

三、扩展方法
使用添加新方法的方式扩展已存在的类型,而不是通过继承的方式
举个例子:

static class ExtensionMethods {
    public static void Demo() {
        decimal x = 1234.568M;
        Console.WriteLine( x.FormattedUS() );
        Console.WriteLine( x.FormattedIT() );
        Console.WriteLine( FormattedUS( x ) ); // Traditional call allowed
        Console.WriteLine( FormattedIT( x ) ); // Traditional call allowed
    }

    static CultureInfo formatUS = new CultureInfo( "en-US" );
    static CultureInfo formatIT = new CultureInfo( "it-IT" );
    public static string FormattedUS( this decimal d ){
        return String.Format( formatIT, "{0:#,0.00}", d );
    }

    public static string FormattedIT( this decimal d ){
        return String.Format( formatUS, "{0:#,0.00}", d );
    }
}

一个扩展方法必须存在于一个static类中,而且本身也必须是public static的
最终要的是this关键字,存在于方法定义时,第一个参数类型的前面,第一个参数的类型就是要扩展的类型

注意:最好是扩展值类型,而不要扩展引用类型,考虑到相关的性能消耗会比较大

扩展方法最通用的用法在自定义的命名空间定义static类,使用using关键子导入到代码中

如果实例方法和扩展方法名字相同时,实例方法的优先级要高

经典实例

public class A {
    public virtual void X() {}
}
public class B : A {
    public override void X() {}
    public void Y() {}
}

static public class E {
    static void X( this A a ) {}
    static void Y( this A b ) {}

    public static void Demo() {
        A a = new A();
        B b = new B();
        A c = new B();

        a.X(); // Call A.X
        b.X(); // Call B.X
        c.X(); // Call B.X

        a.Y(); // Call E.Y
        b.Y(); // Call B.Y
        c.Y(); // Call E.Y
    }
}

四、对象初始化表达式
使用一种简化的方式初始化类,如:

// Implicitly calls default constructor before object initialization
Customer customer = new Customer { Name = "Marco", Country = "Italy" };

// Explicitly specify constructor to call before object initialization
Customer c1 = new Customer() { Name = "Marco", Country = "Italy" };

// Explicitly specify nondefault constructor
Customer c2 = new Customer( "Paolo", 21 ) { Country = "Italy" };

嵌套调用初始化表达式
Rectangle r = new Rectangle {
    TL = new Point { X = 0, Y = 1 },
    BR = new Point { X = 2, Y = 3 }
};

自身对象的初始化(即,在类自身中使用初始化表达式)
Rectangle r = new Rectangle {
    TL = { X = 0, Y = 1 },
    BR = { X = 2, Y = 3 }
};

集合初始化器
List<int> integers = new List<int> { 1, 3, 9, 18 };
List<Customer> list = new List<Customer> {
    new Customer( "Jack", 28 ) { Country = "USA"},
    new Customer { Name = "Paolo" },
    new Customer { Name = "Marco", Country = "Italy" },
};

五、匿名类型
Customer c1 = new Customer { Name = "Marco" };
var c2 = new Customer { Name = "Paolo" };
var c3 = new { Name = "Tom", Age = 31 };
var c4 = new { c2.Name, c2.Age };
var c5 = new { c1.Name, c1.Country };
var c6 = new { c1.Country, c1.Name };

c1 is Customer
c2 is Customer
c3 is <>f__AnonymousType0`2[System.String,System.Int32]
c4 is <>f__AnonymousType0`2[System.String,System.Int32]
c5 is <>f__AnonymousType5`2[System.String,System.String]
c6 is <>f__AnonymousTypea`2[System.String,System.String]


var ints = new[] { 1, 2, 3, 4 };
var ca1 = new[] {
    new Customer { Name = "Marco", Country = "Italy" },
    new Customer { Name = "Tom", Country = "USA" },
    new Customer { Name = "Paolo", Country = "Italy" }
};
var ca2 = new[] {
    new { Name = "Marco", Sports = new[] { "Tennis", "Spinning"} },
    new { Name = "Tom", Sports = new[] { "Rugby", "Squash", "Baseball" } },
    new { Name = "Paolo", Sports = new[] { "Skateboard", "Windsurf" } }
};

查询表达式
var customers = new []{
    new {  Name = "Marco", Discount = 4.5 },
    new {  Name = "Paolo", Discount = 3.0 },
    new {  Name = "Tom", Discount = 3.5 }
};

 var query =
    from c in customers
    where c.Discount > 3
    orderby c.Discount
    select new { c.Name, Perc = c.Discount / 100 };

foreach( var x in query ) {
    Console.WriteLine( x );
}
结果是:
{ Name = Tom, Perc = 0.035 }
{ Name = Marco, Perc = 0.045 }

转换成C# 3.0 的语法后:
var query = customers
            .Where( c => c.Discount > 3)
            .OrderBy( c => c.Discount )
            .Select( c=> new { c.Name, Perc = c.Discount / 100 } );

真是越到后来越没信心了,毕竟第一次接触LINQ,还得继续努力啊



posted on 2008-03-19 11:27  everx  阅读(434)  评论(0编辑  收藏  举报