我有两个接口定义:
// IVector.cs
public interface IVector
{
int Size { get; }
float this[int index] { get; set; }
}
// IMatrix.cs
public interface IMatrix
{
int Size { get; }
float this[int row,int column] { get; set; }
}
以及这些接口的扩展方法
// VectorExtensions.cs
public static T Add<T>(this T vector,T value) where T : struct,IVector
{
var output = default(T);
for (int i = 0; i < output.Size; i++)
output[i] = vector[i] + value[i];
return output;
}
// MatrixExtensions.cs
public static T Add<T>(this T matrix,IMatrix
{
var output = default(T);
for (int i = 0; i < output.Size; i++)
for (int j = 0; j < output.Size; j++)
output[i,j] = vector[i,j] + value[i,j];
return output;
}
所有类型都在同一个命名空间中.
由于某些原因,当从IVector派生的东西调用Add()时,编译器无法确定是使用MatrixExtensions类还是VectorExtensions类中的定义.将其中一个扩展类移动到另一个命名空间停止错误…但是我希望它们在同一个命名空间中:D
为什么会发生这种情况?
编辑:(我不敢相信我忘了添加这个) 为了解决这个问题我该怎么办?
解决方法
您有两个扩展方法,每个方法具有相同的签名.
// VectorExtensions.cs
public static T Add<T>(this T vector,T value)
// MatrixExtensions.cs
public static T Add<T>(this T matrix,T value)
是的,你在你的代码中提供了约束,但是constraints are not part of the signature.所以你有两个方法具有相同的签名,所以这两种方法都不比其他方法更好,而且你有歧义的问题.
将静态扩展方法类中的一个移动到不同的命名空间中的原因是不同的结果是编译器将在扩展搜索外部之前首先在最接近的包含命名空间中寻找扩展方法匹配. (参见C#语言规范的第7.5.5.2节[如下])如果将MatrixExtensions移动到另一个命名空间中,则原始命名空间内的扩展方法调用将明确地解析为VectorExtensions方法,因为它是最接近命名空间.但是,这并不能完全解决您的问题.因为如果它是最接近的扩展方法,因此您仍然可以使用这个VectorExtensions实现方法,因为再次约束不是签名的一部分.
为方便起见,语言规范.
7.5.5.2 Extension method invocations
In a method invocation (§7.5.5.1) of one of the forms
expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )
if the normal processing of the invocation finds no applicable methods,an attempt is made to process the construct as an extension method invocation. The objective is to find the best type-name C,so that the corresponding static method invocation can take place:
C . identifier ( expr )
C . identifier ( expr,args )
C . identifier < typeargs > ( expr )
C . identifier < typeargs > ( expr,args )
The search for C proceeds as follows:
- Starting with the closest enclosing namespace declaration,continuing with
each enclosing namespace declaration, and ending with the containing compilation unit,successive attempts are made to find a candidate set of extension methods:
- If the given namespace or compilation unit directly contains
non-generic type declarations Ci with extension methods Mj that have the name identifier and are accessible and applicable with respect to the desired static method invocation above,then the set of those extension methods is the candidate set.
- If namespaces imported by using namespace directives in the given
namespace or compilation unit directly contain non-generic type declarations Ci with extension methods Mj that have the name identifier and are accessible and applicable with respect to the desired static method invocation above,then the set of those extension methods is the candidate set.
- If no candidate set is found in any enclosing namespace declaration or
compilation unit,a compile-time error occurs.
- Otherwise,overload resolution is applied to the candidate set as
described in (§7.4.3). If no single best method is found,a compile-time error occurs.
- C is the type within which the best method is declared as an extension method. Using C as a target,the method call is then processed as a static method invocation (§7.4.4). The preceding rules mean that instance methods take precedence over extension methods,that extension methods available in inner namespace declarations take precedence over extension methods available in outer namespace declarations,and that extension methods declared directly in a namespace take precedence over extension methods imported into that same namespace with a using namespace directive
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|