不明白为什么这些是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
例如,想要按照约定将
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 T
与 T
不同(或 out T
、 ref 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/