可以在方法调用中推断出1个方法的类型参数,但不能推断为1个参数



我正在尝试创建一个辅助方法来生成MVC下拉列表,我对表达式和反思进行了介绍,并且能够使以下内容工作:

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(...);
}

我可以使用以下代码生成下拉级

DropDown.GenerateDropDown(routes, r => r.Name, r => r.Id, selectedValue, "Please Select One");

此使用类型推理来收集列表(iEnumerable)的数据,并帮助我们确定应分别将属性用作文本以及值,名称和ID。

请注意以上代码有效!但是,我不喜欢将object用作Expression<Func<TSource, object>> value参数的第二个类型参数(它没有很好的IntelliSense)。但是,当我将其更改为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.    

为什么会发生这种情况?如何有1个工作,但是在添加/更改为2时失败?

任何帮助将非常感谢,谢谢!

相关注释:

R.NAME和R.ID的数据类型是什么?

您的回应:

对不起,我看不到数据类型重要,但是名称是字符串,ID是十进制。

您无法理解为什么要解释为什么您会被错误混淆。(通常,您应该永远不要相信您的问题是关于类型推理的类型。类型是唯一重要的推理!

随着您的更改,您需要将TProperty推断为 stringdecimal。当面对这个问题时,C#不会说"字符串和十进制是对象的唯一基本类型"并推断对象。相反,C#说:"这个人认为字符串和小数是同一件事,因此该程序可能是一个错误"。选择对象是错误的事情。

类型推理中C#中的规则是(1)在每个类型参数上确定范围,然后(2)a best type 从类型bends 中选择被选。C#永远不要"魔术"一种新的最佳类型。它从未说过:"嘿,您希望这件事既是狗又是猫,因此必须是动物"。它说:"您希望我在狗和猫之间做出选择,这两个都更好"。

现在,如果被要求在狗和动物之间进行选择,那么显然是更好的:选择越多的动物。但是所选择的类型是从始终选择的一组事物中。

您可以在C#中的许多其他地方看到这一点:

var x = new[] { dog, cat };

这是一个错误,而不是动物阵列。但是

var x = new [] { dog, (Animal)cat };

是一系列动物。

名称是字符串,ID是小数。

TProperty的类型必须是整个方法的类型,您不能将其代表一个位置中的一个数据类型,而在其他位置中则代表不同的数据类型。如果您想拥有单独的数据类型,则在声明中需要3种通用类型。

public static DropDown GenerateDropDown<TSource, TName, TValue>(IEnumerable<TSource> source,
            Expression<Func<TSource, TName>> text,
            Expression<Func<TSource, TValue>> value,
            string selectedValue = "",
            string placeholder = "") where TSource : class
{
    ...
    return new DropDown(...);
}

注意,如果text始终将返回一个字符串,则可以将代码更改为

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

Too

最新更新