c# - 对 "Already defines a member with the same parameter types"错误感到困惑

标签 c# covariance contravariance invariance

不明白为什么这些是Map方法具有相同的参数类型,因为它们也不会出现。这是协方差的问题还是只是通用签名的问题?

我想从总体上理解它,以避免编写出现此问题的代码。 (并解释第 22 条军规:相同和不同)


class A { }
class B
{
    void Map<T>(T obj) where T : A { }
    void Map<T>(T obj) where T : B { } // SAME -- "Map" already defined, can't compile

    void Test(A a, B b)
    {
        Map(a);
        Map(b); // NOT SAME -- if the B-mapper is removed then this won't compile
    }
}

此更改将“修复”它:void Map<T>(in T obj) ??

这看起来更加“不一样”:

Ta Map<Tb, Ta>(Tb obj) where Ta: A, new() where Tb : B, new() { return new Ta(); }
Tb Map<Ta, Tb>(Ta obj) where Ta: A, new() where Tb : B, new() { return new Tb(); } // ERROR

例如,想要按照约定将 从 Tsrc 映射到 Tdest,但不能。 需要交换通用订单:

Ta Map<Ta, Tb>(Tb obj) where Ta: A, new() where Tb : B, new() { return new Ta(); }
Tb Map<Ta, Tb>(Ta obj) where Ta: A, new() where Tb : B, new() { return new Tb(); } // OK NOW

注意:在最后两种情况下,参数类型不会更改,即使其中一个合法而另一个不合法。 in不变性修饰符也可以解决这个问题,我相信这是理解正在发生的事情的线索。

最佳答案

考虑这个例子:

void Map<T>(T obj) where T : struct { }
void Map<T>(T obj) where T : unmanaged { }

Map<int> map = new Map<int>(1);

我们的 map 实例使用哪个版本? Both are just as applicable对于 int 。由于实际签名是相同的,因此它们现在变得不明确。

签名基于参数数量、参数顺序和参数类型。

Generic type constraints不被视为签名的一部分。它们被用作生成实际的类/方法/委托(delegate)等以供运行时使用时要遵循的“规则”。一旦编译器生成运行时所需的通用代码的每个不同版本,就不再需要约束。

void Map<T>(in T obj)确实是与 void Map<T>(T obj) 不同的签名因为in TT 不同(或 out Tref T 等)。

void Map<T>(T obj) where T : A具有与 void Map<T>(T obj) where T : B 相同的签名因为约束已经改变了。 参数数量、参数顺序和参数类型都是相同的。

关于c# - 对 "Already defines a member with the same parameter types"错误感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73818714/

相关文章:

c# - Open CV saturate_cast 函数的 Emgu CV 等价物是什么?

c# - 在 LINQ 中按百分比分组

scala 为抽象数据类型正确定义了一个空值

c# - 无法将任务<List<TEntity>> 转换为任务<IList<TEntity>>

c++ - C++函数指针中的协变和逆变?

c# - 为什么我不能从受约束的泛型集合中推断接口(interface)?

c# - 打开CV非基本形状检测

c# - 是否有在线 XAML 测试器?

python - Numpy 协方差

c# - Autofac:使用 in 和 out 类型参数解析变体类型