“动态”类型可以在通用集合<dynamic>?</dynamic>中安全地变化

时间:2010-02-01 04:37:58

标签: c# .net dynamic c#-4.0

根据我对this question的回答,我想检查一下我对C#4即将推出的dynamic类型的理解。

在这种情况下,我们有一个集合,表示从未知数据库表中提取的记录中的字段。较旧的代码(pre-.Net 4)要求此类集合保留Object类型的项目。抛开这样一个集合的优点,我想知道当你将Object更改为dynamic时会发生什么。

一方面,我希望因为动态类型的东西都是在运行时完成的,所以只要程序员没有对特定项目的预期类型进行任何拼写错误或错误,一切都应该没问题。集合。

另一方面,我想知道前一句中的“全部”这个词。运行时是否可能从第一次访问动态属性时缓存结果,导致使用不同类型的后续调用失败?

4 个答案:

答案 0 :(得分:3)

以下是Sam博客的相关内容,简要介绍了缓存策略。

http://blogs.msdn.com/samng/archive/2008/10/29/dynamic-in-c.aspx

  

DLR检查缓存以查看是否存在   给定的行动已经受到约束   反对当前的论点。   所以在我们的例子中,我们会做一个类型   匹配基于1,2和运行时   d的类型如果我们有缓存命中,   然后我们返回缓存的结果。如果   我们没有缓存命中,那么   DLR检查接收器是否是   一个IDynamicObject。这些人是   本质上是知道如何做的对象   照顾自己的约束力,如此   作为COM IDispatch对象,真实动态   诸如Ruby或Python之类的对象,   或者一些实现的.NET对象   IDynamicObject接口。如果是   其中任何一个,然后DLR取消   到IDO并要求它绑定   行动。

     

注意调用的结果   要绑定的IDO是一个表达式树   表示绑定的结果。   如果它不是IDO,那么DLR   调用语言活页夹(在我们的   case,C#runtime binder)要绑定   操作。 C#运行时绑定程序   将绑定动作,并将返回   一个表达树的表达式树   绑定的结果。一旦完成第2步或第3步   已经发生了,结果   表达式树被合并到   任何缓存机制   后续调用可以针对   缓存而不是反弹。

然而,Sam没有提到的正是缓存未命中策略。有两种主要的缓存未命中策略:(1)当参数类型改变时触发缓存未命中,(2)当参数标识改变时触发缓存未命中。

显然,前者的表现要高得多;当我们只根据类型进行缓存时,锻炼是很棘手的。对所有逻辑如何工作的详细解释需要相当长的时间;希望我或克里斯或山姆会在其中一天做博客文章。

答案 1 :(得分:1)

好吧,我没有等待答案,而是启动了Visual Studio 2010 beta 2,这个测试程序运行良好:

class Foo
{
    public string foo = "Foo!";
}
class Bar
{
    public int bar = 42;
}

class Program
{
    static void Main(string[] args)
    {
        var test = new List<dynamic>();
        test.Add(new Foo());
        test.Add(new Bar());

        Console.WriteLine(test[0].foo.Substring(0,3));
        Console.WriteLine(test[1].bar.ToString("000"));

        Console.ReadKey(true);
    }
}

我想确保不仅检查具有不同名称的属性,而且它们也有不同的类型,并且我使用了每种类型中彼此不兼容的功能。这个似乎建议如果任何东西都被缓存,运行时足够聪明,知道何时使用缓存,何时不使用缓存。我还是想听听是否有人知道这可能不成立的边缘情况,或者对其原因进行更权威的评论。

答案 2 :(得分:1)

你可以将动态视为使用Reflection和MethodInfo.Invoke()编写所有方法调用的语法糖 - 在它下面它不能完全正常工作,但你可以认为它以这种方式工作,与所有“通过动态=&mur;谋杀性行为调用1000方法/秒”的考虑因素一起使用。

答案 3 :(得分:1)

词典 / 列表而言,它只能看到objectdynamic主要在旁观者眼中 - 即调用代码;在引擎盖下它是“物体加一点糖”。所以你不应该在这里看到任何问题。

证明:

    static void Main()
    {
        Console.WriteLine(IsObject<int>()); // false
        Console.WriteLine(IsObject<object>()); // true
        Console.WriteLine(IsObject<dynamic>()); // true
        Console.WriteLine(IsObject<string>()); // false
    }
    static bool IsObject<T>()
    {
        return typeof(T) == typeof(object);
    }