隐式类型的本地变量和数组
a.隐式类型的局部变量
可以赋予局部变量推断“类型”var 而不是显式类型。var 关键字指示编译器根据初始化语句右侧的表达式推断变量的类型。推断类型可以是内置类型、匿名类型、用户定义类型、.NET Framework 类库中定义的类型或任何表达式。有关如何使用 var 初始化数组的更多信息,请参见隐式类型的数组(C# 编程指南)。
下面的示例演示了使用 var 声明局部变量的各种方式:
C# 复制代码
// i is compiled as an int
var i = 5;
// s is compiled as a string
var s = "Hello";
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
// expr is compiled as IEnumerable<Customer>
var expr =
from c in customers
where c.City == "London"
select c;
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
// list is compiled as List<int>
var list = new List<int>();
需要了解的一点是,var 关键字并不意味着“变体”,也不表示该变量是松散类型化变量或后期绑定变量。它只是表示由编译器确定和分配最适当的类型。
var 关键字可在下面的上下文中使用:
在如上示例所示的局部变量(在方法范围中声明的变量)上。
在 for 初始化语句中。
for(var x = 1; x < 10; x++){...}
在 foreach 初始化语句中。
foreach(var item in list){...}
在 using 语句中
using (var file = new StreamReader("C:\\myfile.txt")) {...}
var 和匿名类型
在很多情况下,var 是可选的,它只是提供了语法上的便利。但在使用匿名类型初始化变量时,需要使用它。这在 LINQ 查询表达式中很常见。
由于只有编译器知道匿名类型的名称,因此必须在源代码中使用 var。如果已经使用 var 初始化了查询变量,则还必须使用 var 作为对查询变量进行循环访问的 foreach 语句中迭代变量的类型。
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
// If a query produces a sequence of anonymous types,
// then you must also use var in the foreach statement.
var upperLowerWords =
from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
// Execute the query
foreach (var ul in upperLowerWords)
{
Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
}
}
}
/* Outputs:
Uppercase: APPLE, Lowercase: apple
Uppercase: BLUEBERRY, Lowercase: blueberry
Uppercase: CHERRY, Lowercase: cherry
*/
备注
下列限制适用于隐式类型的变量声明:
只有在同一语句中声明和初始化局部变量时,才能使用 var;不能将该变量初始化为 null。
不能将 var 用于类范围的域。
由 var 声明的变量不能用在初始化表达式中。换句话说,var v = v++; 会产生编译时错误。
不能在同一语句中初始化多个隐式类型的变量。
如果一个名为 var 的类型位于范围中,则当您尝试用 var 关键字初始化局部变量时,将收到编译时错误。
必须使用 var 隐式类型化的局部变量的唯一情况发生在初始化匿名类型时。有关更多信息,请参见匿名类型(C# 编程指南)。
在查询表达式中,当难以确定查询变量的确切构造类型时,您会发现 var 也很有用。这种情况可能发生在分组和排序操作中。
当在键盘上键入变量的具体类型单调乏味时,或者当该类型显而易见或对提高代码可读性没有作用时,var 关键字也可能有用。var 以这种方式发挥作用的一个示例是嵌套的泛型类型,例如在分组操作中使用的那些类型。在下面的查询中,查询变量的类型是 IEnumerable<IEnumerable<Student>>。只要您和其他必须维护您代码的人员了解到这一点,就可以毫无问题地使用隐式类型化,以达到方便和简洁的效果。
// Same as previous example except we use the entire last name as a key.
// Query variable is an IEnumerable<IGrouping<string, Student>>
var studentQuery3 =
from student in students
group student by student.Last;
b.隐式类型的数组
可以创建隐式类型的数组,在这样的数组中,数组实例的类型是从数组初始值设定项中指定的元素推断而来的。有关任何隐式类型变量的规则也适用于隐式类型的数组。有关更多信息,请参见隐式类型的局部变量(C# 编程指南)。
在查询表达式中,隐式类型的数组通常与匿名类型以及对象初始值设定项和集合初始值设定项一起使用。
下面的示例演示如何创建隐式类型的数组:
class ImplicitlyTypedArraySample
{
static void Main()
{
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { "hello", null, "world" }; // string[]
// single-dimension jagged array
var c = new[]
{
new[]{1,2,3,4},
new[]{5,6,7,8}
};
// jagged array of strings
var d = new[]
{
new[]{"Luca", "Mads", "Luke", "Dinesh"},
new[]{"Karen", "Suma", "Frances"}
};
}
}
请注意,在上一个示例中,没有在初始化语句的左侧对隐式类型的数组使用方括号。另请注意,交错数组就像一维数组那样使用 new [] 进行初始化。不支持隐式类型的多维数组。
对象初始值设定项中的隐式类型的数组
创建包含数组的匿名类型时,必须在该类型的对象初始值设定项中对数组进行隐式类型化。在下面的示例中,contacts 是一个隐式类型的匿名类型数组,其中每个匿名类型都包含一个名为 PhoneNumbers 的数组。请注意,对象初始值设定项内部未使用 var 关键字。
var contacts = new[]
{
new {
Name = " Eugene Zabokritski",
PhoneNumbers = new[] { "206-555-0108", "425-555-0001" }
},
new {
Name = " Hanying Feng",
PhoneNumbers = new[] { "650-555-0199" }
}
};
PS:以上来自MSDN