C# 属性getter和具有一个参数的方法之间怎么可能存在歧义?
我不敢相信我以前从未遇到过这种情况,但为什么我会收到这段代码的编译器错误C# 属性getter和具有一个参数的方法之间怎么可能存在歧义?,c#,.net,compiler-errors,ambiguity,C#,.net,Compiler Errors,Ambiguity,我不敢相信我以前从未遇到过这种情况,但为什么我会收到这段代码的编译器错误 public class Main { public Main() { var ambiguous = new FooBar(1); var isConfused = ambiguous.IsValid; // this call is ambiguous } } public class FooBar { public int DefaultId { ge
public class Main
{
public Main()
{
var ambiguous = new FooBar(1);
var isConfused = ambiguous.IsValid; // this call is ambiguous
}
}
public class FooBar
{
public int DefaultId { get; set; }
public FooBar(int defaultId)
{
DefaultId = defaultId;
}
public bool IsValid
{
get { return DefaultId == 0; }
}
public bool IsValid(int id)
{
return (id == 0);
}
}
以下是错误消息:
“FooBar.IsValid”和“FooBar.IsValid(int)”之间存在歧义
为什么这样含糊不清?
我认为有两个原因不应该模棱两可:
IsConfused
之后没有父阶段IsConfused
没有int参数含糊不清的地方在哪里?您可能会收到特定的消息,这让人感到困惑,但让两个成员同名是不合法的(方法重载除外)。在这里,您的属性和方法具有相同的名称。这与不能使用相同名称的属性和内部类的原因相同。字段、属性、方法和内部类都是封闭类型的成员,并且必须具有唯一的名称。出现错误是因为它是不明确的,因为它是使用
var
声明的。它可以是:
bool isConfused = ambiguous.IsValid;
或:
Func isConfused=dimensional.IsValid;
使用var
需要编译器能够推断出确切的含义,在这种情况下,有两种可能性
但是,如果删除
var
,您仍然会得到一个(不同的)错误,因为您不能有两个名称相同的成员,一个是属性,一个是方法。您会得到一个错误,即“FooBar首先已经包含了IsValid的定义”,编译器似乎总能判断出您是在调用该方法还是在使用该属性——毕竟,该方法后面有括号,而该属性没有
不过,这不起作用。可以使用不带括号的方法:
void Foo() { ... }
void Bar(Action action) { ... }
Bar(Foo);
Action MyProperty { get; set; }
MyProperty();
您可以使用带有括号的属性:
void Foo() { ... }
void Bar(Action action) { ... }
Bar(Foo);
Action MyProperty { get; set; }
MyProperty();
确保不存在歧义的唯一方法是不允许具有相同名称的方法和属性。还有一个错误,因为不允许定义两个同名成员:)这一约束是从.Net 1开始实施的吗?@Jon:是的,非常正确。但他显示的错误是由于变量引起的歧义。。。“我编辑后也提到了这一点。”里德·科普西(Reed Copsey)——那么,如果名字改变了,就不会有歧义了。我认为这不是一个正确的答案。@Jon,@manojlds:在您键入时计算错误的引擎与在您构建时计算错误的引擎有着微妙的不同行为。特别是,前者试图处理代码不正确的情况,因为代码正在被积极编辑。在这类情况下,我们有试探法,试图检测和防止“级联”错误,从一个错误中恢复会导致另一个错误;这可能是一种奇怪的、出乎意料的启发式行为。我想你已经知道了,+1。我只在
Main
(不是在FooBar
)上收到了一个错误,但是当我在Main
中注释掉有问题的行并进行编译时,我在FooBar
上收到了一个错误('FooBar'已经包含了IsValid
的定义)。奇怪的是,main中的错误似乎掩盖了FooBar
@DanM中的错误-另一个错误没有被覆盖。当我编译时,我只得到另一个错误,只有VS显示这两个错误。@DanM:从命令行编译时,它不适合我。这是你的密码吗?@Jon Skeet,@manojlds,你们说得对。在构建之前,我只得到了关于模糊性的错误(红色的曲线),但是在构建之后,模糊性错误消失了,我只得到了“已经包含一个定义”的错误(蓝色的曲线)。但是,从技术上讲,属性是函数,这就是为什么它令人困惑的原因。Java的Getter/Setter系统没有这样的问题。很好的解释,+1。奇怪的是,我不知道,直到我建立。我只得到关于模糊性的错误(红色蠕动)。一旦我构建,歧义错误就会消失,我会得到“已经包含一个定义”错误(蓝色曲线)。这可能是Visual Studio中的一个bug吗?@DanM-这就是我在评论@Reed Copsey的答案时所问的问题。VS在这里似乎表现不好。实际上,VS显示了这两个错误,编译只显示了多定义错误,这也是VS应该显示的。@manojlds:问题是,如果参数不同,为什么会得到这个消息?在我看来,这似乎是一个简单的重载名称。但是,如果属性的结果已定义为布尔值,则不能使用带括号的属性。首先,这只解决了属性不明确的一种情况。但是,第二,您希望采用一种可能的功能(“允许属性与方法具有相同的名称”),这种功能一开始就不是很有用,并且只在属性属于某些类型时才允许它,从而降低它的有用性?记住。你没有提出一个非常有说服力的案例。