您将如何使用C#4动态类型?

您将如何使用C#4动态类型?,c#,dynamic,c#-4.0,C#,Dynamic,C# 4.0,C#4将包含一个新的dynamic关键字,该关键字将把动态语言功能引入C# 您计划如何在自己的代码中使用它,您会建议什么模式?在当前项目的哪一部分中,它会使代码更干净或更简单,或者实现您根本无法做到的事情(除了与诸如IronRuby或IronPython之类的动态语言的明显互操作之外) PS:如果你不喜欢这个C#4的添加,请避免负面评论 编辑:重新聚焦问题 大多数stackoverflow C#用户都知道dynamic的经典用法。我想知道的是,你是否想到了一些新的C#模式,在这些模式中,dyna

C#4将包含一个新的
dynamic
关键字,该关键字将把动态语言功能引入C#

您计划如何在自己的代码中使用它,您会建议什么模式?在当前项目的哪一部分中,它会使代码更干净或更简单,或者实现您根本无法做到的事情(除了与诸如IronRuby或IronPython之类的动态语言的明显互操作之外)

PS:如果你不喜欢这个C#4的添加,请避免负面评论

编辑:重新聚焦问题


大多数stackoverflow C#用户都知道dynamic的经典用法。我想知道的是,你是否想到了一些新的C#模式,在这些模式中,dynamic可以有效地利用,而不会失去太多的C#spirit。

我将使用它来简化处理COM/Interop的代码,在这之前,我必须指定要调用的成员及其参数等。(基本上,编译器不知道函数的存在,我需要在编译时对其进行描述)。使用dynamic,这会减少麻烦,代码也会变得更精简。

现在使用老式反射,代码可读性受到损害。正如您所说,还有一些互操作场景(我偶尔使用COM)

差不多就是这样。如果
动态
使用可以避免,就应该避免。编译时检查、性能等等

几周前,我记起了。当我第一次读到它时,坦率地说,我感到很失望。但我没有意识到的是,我甚至不知道如何在某个未知类型上使用运算符。我开始怀疑生成的代码会是什么:

dynamic c = 10;
int b = c * c;
使用常规反射,您不能使用已定义的运算符。它使用
Microsoft
命名空间中的一些内容生成了大量代码。我们只需说上面的代码更容易阅读:)它工作起来很好,但速度也很慢:大约比常规乘法(doh)慢10000倍,与使用乘法方法的
ICalculator
接口相比,速度大约慢100倍

编辑生成的代码,对于感兴趣的人:

if (<Test>o__SiteContainer0.<>p__Sitea == null)
  <Test>o__SiteContainer0.<>p__Sitea =
    CallSite<Func<CallSite, object, object, object>>.Create(
      new CSharpBinaryOperationBinder(ExpressionType.Multiply,
        false, false, new CSharpArgumentInfo[] {
          new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null),
          new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) }));
b = <Test>o__SiteContainer0.<>p__Site9.Target(
      <Test>o__SiteContainer0.<>p__Site9,
      <Test>o__SiteContainer0.<>p__Sitea.Target(
        <Test>o__SiteContainer0.<>p__Sitea, c, c));
if(o_uuusiteContainer0.p_uuusitea==null)
o__站点容器0.p__站点A=
调用站点。创建(
新CSharpBinaryOperationBinder(ExpressionType.Multiply,
false,false,新建CSharpArgumentInfo[]{
新建CSharpArgumentInfo(CSharpArgumentInfoFlags.None,null),
新的CSharpArgumentInfo(CSharpArgumentInfoFlags.None,null)});
b=o__站点容器0.p__站点9.Target(
o__站点容器0.p__站点9,
o__站点容器0.p__站点a.Target(
o__站点容器0.p__站点a,c,c));

dynamic关键字旨在简化两种场景所需的代码:

  • C#到COM互操作
  • C#到动态语言(JavaScript等)的互操作

虽然它可以在这些场景之外使用,但它可能不应该被使用。

Miguel de Icaza在他的博客上介绍了一个非常酷的用例(包括来源):


如果能够以安全可靠的方式实现这一点,那么本机代码互操作将非常棒。

这也将允许我们避免在某些情况下使用访问者模式,因为现在可以进行多分派

public class MySpecialFunctions
{
  public void Execute(int x) {...}
  public void Execute(string x) {...}
  public void Execute(long x) {...}
}

dynamic x = getx();
var myFunc = new MySpecialFunctions();
myFunc.Execute(x);

…将在运行时调用最佳方法匹配,而不是在编译时进行计算

最近,我在博客中介绍了C#4.0中的动态类型,其中我提到了它的一些潜在用途以及它的一些缺陷。这篇文章本身有点太大,放不下,但是你可以在这里完整地阅读

作为总结,这里有几个有用的用例(除了与COM库和动态语言(如IronPython)交互的明显用例):

  • 将随机XML或JSON读入动态C#对象。Net框架包含用于将XML和JSON文档轻松反序列化为C#对象的类和属性,但前提是它们的结构是静态的。如果它们是动态的,并且您需要在运行时发现它们的字段,则只能将它们反序列化为动态对象。Net默认情况下不提供此功能,但可以通过第三方工具(如或)完成
  • 从方法返回匿名类型。匿名类型的作用域被限制在定义它们的方法上,但这可以通过动态方法来克服。当然,这是一件危险的事情,因为您将公开具有动态结构的对象(无需编译时检查),但在某些情况下它可能很有用。例如,以下方法使用Linq to SQL从DB表中仅读取两列并返回结果:

    public static List<dynamic> GetEmployees()
    {
      List<Employee> source = GenerateEmployeeCollection();
      var queyResult = from employee in source
                    where employee.Age > 20
                    select new { employee.FirstName, employee.Age };
    
      return queyResult.ToList<dynamic>();
    }
    
    然后,问题来自这样一个事实:WCF将只返回由序列化对象生成的客户端响应。如果对象是静态的,则无法返回动态响应,因此需要使用动态类型。然而,这里还有最后一个问题,即默认情况下动态类型是不可序列化的。在中,有一个代码示例展示了如何克服这一问题(同样,由于它的大小,我不在这里发布它)


最后,您可能会注意到我提到的两个用例需要一些变通方法或第三方工具。这让我想到,尽管.Net团队在框架中添加了一个非常酷的功能,但他们可能只是在考虑COM和动态语言互操作的情况下才添加它。这将是一个耻辱,因为动态语言有一些强大的优势,在一个将它们与强类型语言的优势相结合的平台上提供动态语言可能会使.Net和C领先于其他开发平台。

重复问题?看不出真的。。。问题不是“你喜欢它吗?”而是你会用它做什么。但这是真的,非常接近。我搜索了一个类似的问题,但没有发现这个问题。这是一个没有“r”的讨论
public static List<dynamic> GetEmployees()
{
  List<Employee> source = GenerateEmployeeCollection();
  var queyResult = from employee in source
                where employee.Age > 20
                select new { employee.FirstName, employee.Age };

  return queyResult.ToList<dynamic>();
}
http://api.example.com/users?userId=xxxx&fields=firstName,lastName,age