【问题标题】:How can there be ambiguity between a property getter and a method with one argument?属性 getter 和具有一个参数的方法之间怎么会有歧义?
【发布时间】:2011-09-30 18:18:21
【问题描述】:

我不敢相信我以前从未遇到过这种情况,但为什么我收到此代码的编译器错误?

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)”之间的歧义

为什么会这样模棱两可?

我认为它不应该模棱两可的原因有两个:

  1. IsConfused 后面没有括号。
  2. IsConfused 没有 int 参数。

歧义在哪里?

【问题讨论】:

    标签: c# .net compiler-errors ambiguity


    【解决方案1】:

    出现错误是因为它是使用var 声明的,因此不明确。可能是:

    bool isConfused = ambiguous.IsValid;
    

    或者:

    Func<int, bool> isConfused = ambiguous.IsValid;
    

    使用var需要编译器能够推断出确切的含义,在这种情况下,有两种可能。

    但是,如果您删除 var,您仍然会收到(不同的)错误,因为您不能有两个同名的成员,一个是属性,一个是方法。

    【讨论】:

    • 还有一个错误,因为您根本不允许定义两个具有相同名称的成员:)
    • 自 .Net 1 以来是否强制执行此约束?
    • @Jon:是的,非常正确。但他显示的错误是由于 var 引起的歧义......我也编辑过提及这一点。
    • @Reed Copsey - 那么,如果名称被更改,那么一开始就不会出现歧义。我不认为这是一个正确的答案。
    • @Jon, @manojlds:在您输入时找出错误的引擎与找出错误的引擎有细微的不同当你构建时。特别是,前者试图处理代码不正确的情况因为它正在被积极编辑。在这些情况下,我们有尝试检测和防止“级联”错误的启发式方法,其中从一个错误中恢复会导致另一个错误;这可能是其中一种启发式的一种奇怪且出乎意料的行为。
    【解决方案2】:

    您会收到该特定消息令人困惑,但拥有两个同名成员是不合法的(方法重载除外)。在这里,您的属性和方法具有相同的名称。这与您不能拥有同名的属性和内部类的原因相同。字段、属性、方法和内部类都是封闭类型的成员,并且必须具有唯一的名称。

    【讨论】:

    • 我想你已经明白了,+1。我只在Main(不是FooBar)上收到错误,但是当我在Main 中注释掉有问题的行并编译时,我收到FooBar 的错误('Foobar' 已经包含一个定义对于IsValid)。奇怪的是main中的错误似乎掩盖了FooBar中的错误。
    • @DanM - 未涵盖其他错误。当我编译时,我只得到另一个错误,只有 VS 显示这两个错误。
    • @DanM:从命令行编译时不适合我。 正是这段代码对你有用吗?
    • @Jon Skeet,@manojlds,你们是对的。在构建之前我只收到关于歧义的错误(红色曲线),但在我构建之后,歧义错误消失了,我只收到“已经包含定义”错误(蓝色曲线)。
    • 从技术上讲,属性是函数,这就是它令人困惑的原因。 Java 的 Getter/Setter 系统没有这样的问题。不过很好的解释,+1。
    【解决方案3】:

    您会收到“FooBar 已经包含 IsValid 的定义”的错误消息

    【讨论】:

    • 奇怪的是,我直到我建立。我只得到关于歧义的错误(红色曲线)。一旦我构建,歧义错误就会消失,并且我得到“已经包含定义”错误(蓝色曲线)。这可能是 Visual Studio 中的错误吗?
    • @DanM - 这就是我在 @Reed Copsey 的答案中在 cmets 中提出的问题。 VS 似乎在这里表现错误。其实VS显示了这两个错误,编译只显示多定义错误,这也是VS应该显示的。
    • @manojlds:问题是,如果参数不同,您为什么会收到该消息?对我来说似乎是一个简单的重载名称。
    【解决方案4】:

    起初,编译器似乎总能判断出你是在调用方法还是使用属性——毕竟,方法后面有括号,而属性没有。

    不过,这不成立。您可以使用不带括号的方法:

    void Foo() { ... }
    void Bar(Action action) { ... }
    
    Bar(Foo);
    

    您可以使用带有括号的属性:

    Action MyProperty { get; set; }
    
    MyProperty();
    

    确保没有歧义的唯一方法是禁止使用同名的方法和属性。

    【讨论】:

    • 如果属性的结果已经被定义为布尔值,则不能使用带括号的属性。
    • 首先,这仅解决了其中一种模棱两可的情况。但其次,您希望采用一个可能的功能(“允许属性与方法具有相同的名称”),该功能一开始并不是很有用,并通过仅在以下情况下才允许它不太有用财产属于某些类型?请记住,every feature starts with minus 100 points。你没有提出一个非常有说服力的案例。
    猜你喜欢
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多