您的位置:首页 > 编程语言 > C#

C# 3.0的新特性

2008-03-19 11:27 295 查看
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,还得继续努力啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: