方法调用中可以推断出方法的类型参数为1而不是2个参数

Tyl*_*ler 0 c# asp.net-mvc

我正在尝试创建一个帮助方法来为MVC生成DropDown我已经用表达式和反射进行了一些操作,并且能够使以下工作:

public static DropDown GenerateDropDown<TSource, TProperty>(IEnumerable<TSource> source,
            Expression<Func<TSource, TProperty>> text,
            Expression<Func<TSource, object>> value,
            string selectedValue = "",
            string placeholder = "") where TSource : class
        {
...
return new DropDown(...);
}
Run Code Online (Sandbox Code Playgroud)

我可以使用以下代码生成DropDown

DropDown.GenerateDropDown(routes, r => r.Name, r => r.Id, selectedValue, "Please Select One");
Run Code Online (Sandbox Code Playgroud)

这使用类型推断来收集列表(IEnumerable)的数据,并帮助我们确定哪些属性应分别用作Text和Value,Name和Id.

注意上面的代码有效!但是我不喜欢使用object作为参数的第二个类型Expression<Func<TSource, object>> value参数(它不能提供良好的智能感知).但当我将其更改为Expression<Func<TSource, TProperty>> value(就像上面的参数)时,我得到以下错误:

Error   CS0411  The type arguments for method 'DropDown.GenerateDropDown<TSource, TProperty>(IEnumerable<TSource>, Expression<Func<TSource, TProperty>>, Expression<Func<TSource, TProperty>>, string, string)' cannot be inferred from the usage. Try specifying the type arguments explicitly.    
Run Code Online (Sandbox Code Playgroud)

为什么会这样?怎么可能有1个工作但是当添加/更改为2时它失败了?

非常感谢任何帮助,提前感谢!

Eri*_*ert 5

相关评论:

r.Name和r.Id的数据类型是什么?

你的回应:

抱歉,我无法看到数据类型的重要性,但Name是一个字符串,Id是一个小数.

你无法理解为什么重要的是解释为什么你会被错误所迷惑.(一般来说,当你的问题是关于类型推断的时候,你永远不应该相信这些类型并不重要.类型推断中唯一重要的类型!)

随着你的改变,你需要TProperty被推断为 stringdecimal.当遇到这个问题时,C#并没有说"字符串常见的唯一基类型和十进制是对象"而是推断对象.更确切地说,C#说"这个人认为字符串和小数是相同的,因此程序可能是一个错误".选择对象在这里做错了.

C#中用于类型推断的规则是(1)在每个类型参数上确定边界,然后(2)选择从类型边界中选择最佳类型.C#永远不会"魔法化"成为一种新的最佳类型.它永远不会说,"嘿,你想要这个东西既是狗又是猫,因此它必须是动物".它说"你希望我在狗和猫之间做出选择,而且两者都不是更好".

现在,如果被要求在狗和动物之间做出选择,那么一个明显更好:选择更普通的动物类型.但是,所选择的类型总是来自要从中选择的一组事物.

你可以在C#的许多其他地方看到这个:

var x = new[] { dog, cat };
Run Code Online (Sandbox Code Playgroud)

这是一个错误,而不是一系列动物.但

var x = new [] { dog, (Animal)cat };
Run Code Online (Sandbox Code Playgroud)

是一系列动物.