为什么使用+运算符的字符串连接与C#中的动态类型一起使用?

时间:2012-07-29 05:51:10

标签: c# string dynamic expression-trees dynamic-language-runtime

我最近看到了一个示例,证明以下内容有效:

T Add<T>(dynamic a, dynamic b)
{
    return a + b;
}

Add<string>("hello", "world");  // Returns "helloworld"

但是,如果我尝试使用表达式来创建“通用”添加功能:

ParameterExpression left = Expression.Parameter(typeof(T), "left");
ParameterExpression right = Expression.Parameter(typeof(T), "right");
var add = Expression.Lambda<Func<T, T, T>>(Expression.Add(left, right), left, right).Compile();  // Fails with System.InvalidOperationException : The binary operator Add is not defined for the types 'System.String' and 'System.String' when T == String.

然后将此函数与字符串一起使用,它失败,因为String类型实际上并不实现+运算符,而只是String.Concat()的语法糖。

那么,动态允许这种方式有效吗?我认为在运行时它已超过使用String.Concat()重写+的点。

3 个答案:

答案 0 :(得分:6)

dynamic使用复制C#编译器规则的运行时辅助函数。即使框架未定义任何运算符,其中一条规则也允许在+个对象上string。诸如int之类的标准数字类型也没有自定义运算符重载,这也是由编译器完成的,并且在使用dynamic时需要在运行时执行。这就是您需要对Microsoft.CSharp.dll的引用的原因:dynamic在没有这些帮助函数的情况下无法工作。

答案 1 :(得分:3)

根据文档,也许代替Expression.Add(left, right)您可以说Expression.Add(left, right, method)其中method是静态MethodInfo的{​​{1}}。

String.Concat(String, String)

编辑:嗯,我的答案有点忽略了这一点。有趣的问题是:当运行时尝试解析编译器在没有类型检查的情况下通过的var method = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), }); 时,运行时会考虑哪些操作? Bulit-另外还有数字类型?字符串连接?委托连接?用户定义的运算符重载?

答案 2 :(得分:0)

在你的第一个例子中,a和be仍然是字符串(试试这个):

// Define other methods and classes here
T Add<T>(dynamic a, dynamic b)
{
    Console.WriteLine(a.GetType());
    Console.WriteLine(b.GetType());
    return a + b;
}

也许这更有意义?

void Main()
{
var x = Add<string>(new { val = "hello"},new { val = "world"});  // Returns "hello world"  
Console.WriteLine(x);
}

// Define other methods and classes here
T Add<T>(dynamic a, dynamic b)
{
    return a.val + b.val;
}