奇怪的行为随着var,dynamic和linq的组合而改变 [英] Odd behaviour change with var, dynamic and linq combination
问题描述
var
,并在代码的完全不同的部分得到了一个奇怪的运行时异常。将var更改为int可以修复运行时异常,但我看不清为什么。我把代码放在这个例子中; public class Program
{
private static List< string> Test(string i){return new List< string> {一世}; }
private static dynamic GetD(){return 1; }
public static void Main()
{
int value1 = GetD(); //< - int
var result1 = Test(Value+ value1);
//没问题,打印Value 1,List上的First()< string>工程很好
Console.WriteLine(result1.First());
var value2 = GetD(); //< - var
var result2 = Test(Value+ value2);
//下面的行给出了RuntimeBinderException
//'System.Collections.Generic.List< string>'不包含$'
//'First'
控制台的定义。的WriteLine(result2.First());
}
}
我可以看到var的类型动态而不是int,但为什么这种类型传播到并影响调用返回值的行为 Test()
?
编辑:也许我应该澄清我的问题;我可以看到,动态
传播到 result2
,我不明白是为什么当IDE清楚地表示列表与LT;串GT; Test(string)
是调用的方法,它仍然将返回值推定为动态。这是IDE比编译器更聪明的情况吗?
您的代码编译如下:
public static void Main()
{
int value1 = GetD(); //< - int
列表< string> result1 = Test(Value+ value1);
//没问题,打印Value 1,List上的First()< string>工程很好
Console.WriteLine(result1.First());
动态value2 = GetD(); //< - var
dynamic result2 = Test(Value+ value2);
//下面的行给出了RuntimeBinderException
//'System.Collections.Generic.List< string>'不包含$'
//'First'
控制台的定义。的WriteLine(result2.First());
}
result2
是一个动态对象,那么它不支持扩展方法(用作扩展方法)。
但是,您可以这样做:
Console.WriteLine(Enumerable.First(result2));
更新
您的IDE不是聪明。尝试添加新的方法:
private static List< int> Test(int i){return new List< int> { 一世 }; }
它将为您提供两种可能性。
更新2
C#规范第7.6.5段:
如果至少有一个
成立,则调用表达式是动态绑定的(§7.2.2):
- 主要-expression具有编译时类型动态。
- 可选参数列表的至少一个参数的编译时类型为dynamic,primary-expression不具有委托类型。
I (lazily) used var
in the original version of the below code and got a strange runtime exception in an entirely different part of the code. Changing "var" to "int" fixed the runtime exception but I cannot quite see why. I boiled the code down to this example;
public class Program
{
private static List<string> Test(string i) { return new List<string> {i}; }
private static dynamic GetD() { return 1; }
public static void Main()
{
int value1 = GetD(); // <-- int
var result1 = Test("Value " + value1);
// No problem, prints "Value 1", First() on List<string> works ok.
Console.WriteLine(result1.First());
var value2 = GetD(); // <-- var
var result2 = Test("Value " + value2);
// The below line gives RuntimeBinderException
// 'System.Collections.Generic.List<string>' does not contain a
// definition for 'First'
Console.WriteLine(result2.First());
}
}
I can see the type of the "var" being dynamic instead of int, but why does that type propagate to and affect the behaviour of the return value of the call to Test()
?
EDIT: Maybe I should clarify my question; I can see that dynamic
propagates to result2
, what I cannot understand is why, when the IDE clearly indicates that List<string> Test(string)
is the method called, it still infers the return value as dynamic. Is it a case of the IDE being more clever than the compiler?
Your code is compiled like this:
public static void Main()
{
int value1 = GetD(); // <-- int
List<string> result1 = Test("Value " + value1);
// No problem, prints "Value 1", First() on List<string> works ok.
Console.WriteLine(result1.First());
dynamic value2 = GetD(); // <-- var
dynamic result2 = Test("Value " + value2);
// The below line gives RuntimeBinderException
// 'System.Collections.Generic.List<string>' does not contain a
// definition for 'First'
Console.WriteLine(result2.First());
}
result2
is a dynamic object, then extention method is not supported on it (used as extention method).
However, you can do this:
Console.WriteLine(Enumerable.First(result2));
UPDATE
Your IDE is not so clever. Try to add the new method:
private static List<int> Test(int i) { return new List<int> { i }; }
It will propose you the two possibilities.
UPDATE2
Paragraph 7.6.5 of the C# specification:
An invocation-expression is dynamically bound (§7.2.2) if at least one of the following holds:
- The primary-expression has compile-time type dynamic.
- At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.
这篇关于奇怪的行为随着var,dynamic和linq的组合而改变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!