c# - 为什么下面的电话是模棱两可的?

标签 c# .net ambiguous-call

以下调用将失败,因为编译器需要方法 SetAll(PropertyInfo, int)

var infos = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

var setters = infos.Select(SetAll); // no overload matches delegate.

private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);

所以这意味着编译器不能以任何方式使用这个重载。它不能将 int 转换为 object

考虑到这一点,为什么以下调用不明确?

var b = infos.Select(SetAll); // ambiguous between Select<PropertyInfo, int, Action>
                              //              and  Select<PropertyInfo, Action>

private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);

private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);

如果编译器不能以任何方式对对象使用重载,那么为什么它会在这里挣扎?


这是我拥有的实际代码。我可以很容易地处理这个问题,但我只是好奇。

var infos = GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

if (useDefaultsOnReset)
{
    var defaults = infos.Select(GetAll);
    _resetters = infos.Zip(defaults, SetAll).ToArray();
}
else
{
    _resetters = infos.Select(SetAll).ToArray(); // error
}

private object GetAll(PropertyInfo info) => info.GetValue(this);
private Action SetAll(PropertyInfo info, object obj) => () => info.SetValue(this, obj);
private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);

最佳答案

这是因为 System.Func<in T1, in T2, out TResult>在其参数类型上是逆变的。这由 in 表示相应类型参数的修饰符。这意味着它匹配任何接受 T1 类型参数的函数。或任何类型 T1可以分配给 T2 类型的参数或任何类型 T2可以分配给。您的第一个签名与 Enumerable.Select 的重载匹配不包含索引。但是,您的第二个签名实际上与 Enumerable.Select 的重载匹配确实包含索引,因为 int可分配给 object .

为了证明这一点。只需创建一个任意类并像这样更改您的程序。

private Action SetAll(PropertyInfo info, A a) => () => info.SetValue(this, obj);
private Action SetAll(PropertyInfo info) => () => info.SetValue(this, null);

class A {}

您将观察到错误消失为 int不可分配给 A .

正如评论中所讨论的,我没有考虑到一个问题。逆变关系在引用类型之间和不限于值类型的泛型之间存在,但在采用 int 的委托(delegate)之间直接分配时它特别不起作用。和 object 给定

Func<int, Action> f;

Func<object, Action> g;

以下都是错误

g = f;
f = g;

但是,如果我们替换 int说一些类A

Func<A, Action> f;

Func<object, Action> g;

第一个是错误,因为对象不是 A,但第二个成功,如上所述。

g = f;
f = g;

关于c# - 为什么下面的电话是模棱两可的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41429427/

相关文章:

c# - 修复 xaml 文件中的大小

c# - C# SSH .Net 库中的 Sudo 命令

c# - 什么使 Min(byte,int) 调用不明确?

C++ 继承错误 : ambiguous error

c# - 查找图表中点的值

c# - Crystal Reports 搞乱富文本

c# - 从现有类 : inheritance or partial classes? 创建新类

c# - 使用模板打印

c# - 上传图像并获取其字节

c++ - ISO C++ 说这些是模棱两可的,