C# 3.0新功能(转)
C# 3.0新功能
• 隐式类型的本地变量和数组
• 对象初始值设定项
• 集合初始值设定项
• 自动实现的属性
• 匿名类型
• 扩展方法
• 分部方法定义
• Lambda 表达式
隐式类型的数组
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { "hello", null, " world" }; string[] 型的数组使用方括号
var c = new[]
{
new[]{1,2,3,4},
new[]{5,6,7,8}
};
var d = new[]
{
new[]{"Luca", "Mads", "Luke", "Dinesh"},
new[]{"Karen", "Suma", "Frances"}
};
1.没有在初始化语句的左侧对隐式类
2.交错数组就像一维数组那样使用
3.不支持隐式类型的多维数组
• var和匿名类型
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
var upperLowerWords =
from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
foreach (var ul in upperLowerWords)
{
Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
}
} }
1.很多时候var是可以省略的
2.但在使用匿名类型初始化变量时,必须使用它
• 对象初始值设定项
使用对象初始值设定项可以在创建对象时向对象的任何可访问的
字段或属性分配值,而无需显式调用构造函数
private class Cat
{
// Auto-implemented properties
public int Age { get; set; }
public string Name { get; set; }
}
static void MethodA()
{
// Object initializer
Cat cat = new Cat { Age = 10, Name = "Sylvester" };
}
3.由于只有编译器知道匿名类型的名称,因此必须在源代码中使用var。
4.如果已经使用var 初始化了查询变量,则还必须使用var 作为对查询变
量进行循环访问的foreach 语句中迭代变量的类型
• 将对象初始值设定项用于匿名类型
查询表达式经常使用匿名类型,而这些类型只能使用对象初始值
设定项进行初始化
var productInfos =
from p in products
select new { p.ProductName, p.UnitPrice };
创建匿名类型时重命名字段
select new {p.ProductName, Price = p.UnitPrice};
• 集合初始值设定项
1.使用集合初始值设定项可以在初始化一个实现了IEnumerable
的集合类时指定一个或多个元素初始值设定项
2.元素初始值设定项可以是简单的值,也可以是表达式或对象初
始值设定项
3.通过使用集合初始值设定项,无需在源代码中指定多个对该类
的Add 方法的调用;编译器会添加这些调用。
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };
• 集合初始值设定项
下面的集合初始值设定项使用对象初始值设定项来初始化在前面
的一个示例中定义的Cat 类的对象。请注意,各个对象初始值设
定项被分别括在大括号中,并且用逗号分隔。
List<Cat> cats = new List<Cat>
{
new Cat(){ Name="Sylvester", Age=8 },
new Cat(){ Name="Whiskers", Age=2},
new Cat() { Name="Sasha", Age=14}
};
List<Cat> moreCats = new List<Cat>
{
new Cat(){ Name="Furrytail", Age=5 },
new Cat(){ Name="Peaches", Age=4},
null
};
如果集合的Add 方法允许,可以将null 指定为集合初始值设定
项中的一个元素
• 自动实现的属性
– 当属性访问器中不需要其他逻辑时,自动实现的属性可使属性声
明变得更加简洁
class LightweightCustomer
{
public double TotalPurchases { get; set; }
public string Name { get; private set; } // read-only
public int CustomerID { get; private set; } // read-only
}
自动实现的属性必须同时声明get 和set 访问器。若要创建readonly 自动实
现属性,请给予它private set 访问器。
自动实现的属性(Property) 不允许具有属性(Attribute)。如果您必须在属性
(Property) 的后备字段上使用属性(Attribute),则应该只创建常规属性
(Property)。
• 匿名类型
– 匿名类型提供了一种方便的方法,可用来将一组只读属性封装到
单个对象中,而无需首先显式定义一个类型。
– 类型名由编译器生成,并且不能在源代码级使用。
– 这些属性的类型由编译器推断
var v = new { Amount = 108, Message = "Hello" };
– 匿名类型通常用在查询表达式的select 子句中,以便返回源序列
中每个对象的属性子集
– 匿名类型是使用new 运算符和对象初始值设定项创建的
– 匿名类型是由一个或多个公共只读属性组成的类类型。不允许包
含其他种类的类成员(如方法或事件)。
• 匿名类型
– 最常见的方案是用其他类型的一些属性初始化匿名类型
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
在将匿名类型分配给变量时,必须使用var 构造初始化该变量。
这是因为只有编译器能够访问匿名类型的基础名称
• 匿名类型
– 匿名类型是直接从对象派生的引用类型。尽管应用程序无法访问
匿名类型,但编译器仍会为其提供一个名称。
– 如果两个或更多个匿名类型以相同的顺序具有相同数量和种类的
属性,则编译器会将这些匿名类型视为相同的类型,并且它们共
享编译器生成的相同类型信息。
– 匿名类型具有方法范围。
– 匿名类型不能像属性一样包含不安全类型。
– 由于匿名类型上的Equals 和GetHashCode 方法是根据属性的
Equals 和GetHashcode 定义的,因此仅当同一匿名类型的两个
实例的所有属性都相等时,这两个实例才相等。