我正在尝试创建一个帮助方法来为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时它失败了?
非常感谢任何帮助,提前感谢!
相关评论:
r.Name和r.Id的数据类型是什么?
你的回应:
抱歉,我无法看到数据类型的重要性,但Name是一个字符串,Id是一个小数.
你无法理解为什么重要的是解释为什么你会被错误所迷惑.(一般来说,当你的问题是关于类型推断的时候,你永远不应该相信这些类型并不重要.类型推断中唯一重要的类型!)
随着你的改变,你需要TProperty被推断为两 string和decimal.当遇到这个问题时,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)
是一系列动物.
| 归档时间: |
|
| 查看次数: |
130 次 |
| 最近记录: |