扩展方法冲突
假设我有 2 个字符串扩展方法,位于 2 个不同的命名空间中:
namespace test1
{
public static class MyExtensions
{
public static int TestMethod(this String str)
{
return 1;
}
}
}
namespace test2
{
public static class MyExtensions2
{
public static int TestMethod(this String str)
{
return 2;
}
}
}
这些方法只是举例,它们实际上并没有做任何事情。
现在让我们考虑这段代码:
using System;
using test1;
using test2;
namespace blah {
public static class Blah {
public Blah() {
string a = "test";
int i = a.TestMethod(); //Which one is chosen ?
}
}
}
问题:
我知道只会选择其中一种扩展方法。
会是哪一个呢?为什么?
编辑:
这也让我烦恼,但并没有那么困扰,因为它毕竟是静态类中的静态方法:
如何从某个命名空间中选择某个方法?
通常我会使用 Namespace.ClassNAME.Method()
...但这恰恰击败了扩展方法的整个想法。我认为你不能使用 Variable.Namespace.Method()
Lets say I have 2 extension methods to string, in 2 different namespaces:
namespace test1
{
public static class MyExtensions
{
public static int TestMethod(this String str)
{
return 1;
}
}
}
namespace test2
{
public static class MyExtensions2
{
public static int TestMethod(this String str)
{
return 2;
}
}
}
These methods are just for example, they don't really do anything.
Now lets consider this piece of code:
using System;
using test1;
using test2;
namespace blah {
public static class Blah {
public Blah() {
string a = "test";
int i = a.TestMethod(); //Which one is chosen ?
}
}
}
The Question:
I know that only one of the extension methods will be chosen.
Which one will it be ? and why ?
Edit:
This also bothers me, but not as much because it's a static method in a static class after all:
How can I choose a certain method from a certain namespace ?
Usually I'd use Namespace.ClassNAME.Method()
... But that just beats the whole idea of extension methods. And I don't think you can use Variable.Namespace.Method()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
不会选择任何方法:调用不明确并且无法编译。
为什么不能执行
Namespace.ClassNAME.Method()
?当然,没有什么可以阻止您将扩展方法视为普通的静态方法,事实上,这是修复歧义并使程序编译的唯一方法。No method will be chosen: the call is ambiguous and will not compile.
Why can't you do
Namespace.ClassNAME.Method()
? Certainly there is nothing that prevents you from treating extension methods as normal static methods, and in fact this is the only way for you to fix the ambiguity and have the program compile.我有这个确切的问题,所以两年后我找到了这篇文章。但是,我认为重要的是要注意,如果调用重复扩展方法的代码与以下代码不在同一命名空间中,则这不会编译并给出“调用不明确”错误其中之一。
如果 OP 要将其类 Blah 的命名空间更改为
test1
或test2
,则代码将编译,并且扩展将在相同的版本中进行编译。使用调用者的命名空间 - 即使两个命名空间都在usings
中表示。因此,如果 Blah 位于test1
命名空间中,则返回“1”,如果 Blah 位于test2
中命名空间,返回“2”。我认为添加到上述答案中很重要,因为我认为一个主流用例是在引用外部扩展库的本地类库中进行扩展(例如,开发人员共享一个公共实用程序库,但有一些本地自定义扩展可能无意中具有相同的名称)。通过将自定义本地扩展维护在与使用它们的代码相同的命名空间中,您可以维护扩展调用语法,而不必恢复将它们视为静态方法调用。
I had this exact question so I found this post two years later. However, I think it is important to note that this will only not compile and give the "The call is ambiguous" error if the code calling the duplicate extension methods is not in the same namespace as one of them.
If the OP were to change the namespace of his class Blah to either
test1
ortest2
, then the code compiles, and the extension in the same namespace as the caller is used - even when both namespaces are represented in theusings
. So if Blah is in thetest1
namespace, "1" is returned, and if Blah is in thetest2
namespace, "2" is returned.I think this is important to add to the above answers, because I think one mainstream use-case is to have extensions in a local class library that references external extension libraries (e.g. devs share a common utility library, but have some local custom extensions that might unwittingly have the same name). By maintaining the custom local extensions in the same namespace as the code that uses them, you can maintain the extension call syntax and not have to revert to treating them as static method calls.
正如 Jon 所说,如果编译时这两者都存在,编译就会失败。
但是,如果编译时仅存在一个,并且稍后更新外部库以添加第二个,则您编译的代码仍将继续使用第一个。这是因为编译器会内部将代码转换为调用namespace.classname.method 的普通形式。
As Jon says, if both of these exist when you do the compilation, the compilation will just fail.
But if only one exists at the time of compilation and a external library later gets updated to add the second, the code you compiled will still continue to use the first one. This is because the compiler interally turns your code into the longhand form of calling namespace.classname.method.
我将大型解决方案从 .Net 4.7.1 迁移到 .Net 4.7.2。我们在代码中使用 LINQ,并使用名为 MoreLinq https://www 的知名且成熟的库.nuget.org/packages/morelinq/。
.Net 4.7.1 没有 .ToHashSet() 方法。我们使用了 MoreLinq 库中的
.ToHashSet()
。在同一个 cs 文件的同一个类中,我们同时拥有using System.Linq;
和using MoreLinq;
。我将项目重新定位到 .Net 4.7.2,编译器显示如上所述的
调用不明确
错误。原因是.Net 4.7.2添加了同名的新扩展方法.ToHashSet()
。我无法重新实现庞大的代码库。我无法用其他库替换 MoreLinq。这就是我所做的。我在一个新文件中创建了一个新类,其中有
using System.Linq;
但没有using MoreLinq;
。这是文件(ToHashsetHelpers.cs):我将整个解决方案中的所有
.ToHashSet()
重命名为.ToHashset()
。I migrated big solution from .Net 4.7.1 to .Net 4.7.2. We use LINQ in our code, and we use well known and established library with name MoreLinq https://www.nuget.org/packages/morelinq/.
.Net 4.7.1 does not have
.ToHashSet()
methods. We used.ToHashSet()
from MoreLinq library. And in the same class in the same cs-file we have bothusing System.Linq;
andusing MoreLinq;
.I retargeted a project to .Net 4.7.2 and the compiler showed
The call is ambiguous
error as described above. The reason was that .Net 4.7.2 added new extension methods with the same name.ToHashSet()
.I cannot reimplement huge code base. I cannot replace MoreLinq with another library. This is what I did. I created a new class in a new file where I have
using System.Linq;
but notusing MoreLinq;
. This is the file (ToHashsetHelpers.cs):And I renamed all
.ToHashSet()
to.ToHashset()
in entire solution.我想知道同样的问题,我在 ASP.NET Core 6 项目中做了一个快速测试。
如果你尝试这样做,它不会编译。与不涉及扩展方法的其他不明确调用或语句非常相似。
替代方案:如果同一名称空间中存在扩展方法,则使用“更接近的方法”;否则无法编译。
I was wondering about the same question and I did a quick test inside an asp.net core 6 project.
If you try this, it does not compile. Pretty much similar as other ambiguous calls or statements not involving extension methods.
Alternative: If there is an extension method in the same namespace, this 'closer one' is used; otherwise it won't compile.