gpt4 book ai didi

c# - C# 中动态类型的限制

转载 作者:太空狗 更新时间:2023-10-29 22:03:27 25 4
gpt4 key购买 nike

您能给我一些限制 C# 中动态类型的原因吗?我在“Pro C# 2010 和 .NET 4 平台”中读到了它们。这是摘录(如果在这里引用书籍是非法的,请告诉我,我会删除摘录):

While a great many things can be defined using the dynamic keyword, there are some limitations regarding its usage. While they are not show stoppers, do know that a dynamic data item cannot make use of lambda expressions or C# anonymous methods when calling a method. For example, the following code will always result in errors, even if the target method does indeed take a delegate parameter which takes a string value and returns void.

dynamic a = GetDynamicObject(); 
// Error! Methods on dynamic data can’t use lambdas!
a.Method(arg => Console.WriteLine(arg));

To circumvent this restriction, you will need to work with the underlying delegate directly, using the techniques described in Chapter 11 (anonymous methods and lambda expressions, etc). Another limitation is that a dynamic point of data cannot understand any extension methods (see Chapter 12). Unfortunately, this would also include any of the extension methods which come from the LINQ APIs. Therefore, a variable declared with the dynamic keyword has very limited use within LINQ to Objects and other LINQ technologies:

dynamic a = GetDynamicObject(); 
// Error! Dynamic data can’t find the Select() extension method!
var data = from d in a select d;

提前致谢。

最佳答案

Tomas 的猜想很不错。他对扩展方法的推理是正确的。基本上,为了使扩展方法起作用,我们需要调用站点在运行时以某种方式知道在编译时哪些 using 指令生效。我们根本没有足够的时间或预算来开发一个可以将此信息保存到调用站点的系统。

对于lambdas来说,情况其实比判断lambda是去表达式树还是delegate这个简单的问题要复杂的多。请考虑以下事项:

d.M(123)

其中 d 是动态类型的表达式。 *什么对象应该在运行时作为参数传递给调用站点“M”?很明显,我们通过了 123 框并通过了它。然后,运行时绑定(bind)器中的重载解析算法会查看 d 的运行时类型和 int 123 的编译时类型,并使用它们。

如果是的话会怎样

d.M(x=>x.Foo())

现在我们应该传递什么对象作为参数?我们无法表示“一个变量的 lambda 方法,它调用一个名为 Foo 的未知函数,无论 x 的类型是什么”。

假设我们想要实现这个功能:我们必须实现什么?首先,我们需要一种方法来表示一个未绑定(bind)的 lambda。表达式树的设计目的只是为了表示所有类型和方法都已知的lambda。我们需要发明一种新的“无类型”表达式树。然后我们需要在运行时绑定(bind)器中实现 所有 lambda 绑定(bind)规则。

考虑最后一点。 Lambda 可以包含语句实现此功能需要运行时绑定(bind)器包含完整 C# 中每个可能语句的语义分析器

这超出了我们的预算几个数量级。如果我们想要实现该功能,我们今天仍将致力于 C# 4。

不幸的是,这意味着 LINQ 不能很好地处理动态,因为 LINQ 当然到处都使用无类型的 lambda。希望在 C# 的某些假设的 future 版本中,我们将拥有功能更完备的运行时绑定(bind)程序,并能够对未绑定(bind)的 lambda 进行同象表示。但如果我是你,我不会屏住呼吸等待。

更新:一条评论要求澄清有关语义分析器的问题。

考虑以下重载:

class C {
public void M(Func<IDisposable, int> f) { ... }
public void M(Func<int, int> f) { ... }
...
}

和一个电话

d.M(x=> { using(x) { return 123; } });

假设 d 是编译时类型 dynamic 和运行时类型 C。运行时绑定(bind)器必须做什么?

运行时绑定(bind)程序必须在运行时确定表达式 x=>{...} 是否可转换为 M 的每个重载中的每个委托(delegate)类型.

为此,运行时绑定(bind)器必须能够确定第二个重载不适用。如果适用,那么您可以将 int 作为 using 语句的参数,但 using 语句的参数必须是一次性的。这意味着运行时绑定(bind)器必须知道 using 语句的所有规则,并且能够正确报告 using 语句的任何可能使用是合法还是非法

显然,这并不局限于 using 语句。运行时绑定(bind)程序必须了解所有 C# 的所有规则,以便确定给定的语句 lambda 是否可转换为给定的委托(delegate)类型。

我们没有时间编写一个运行时绑定(bind)器,它本质上是一个生成 DLR 树而不是 IL 的全新 C# 编译器。通过不允许 lambda,我们只需要编写一个知道如何绑定(bind)方法调用、算术表达式和其他一些简单类型的调用站点的运行时绑定(bind)器。允许使用 lambda 会使运行时绑定(bind)问题的实现、测试和维护成本提高数十倍或数百倍。

关于c# - C# 中动态类型的限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3588956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com