代码之家  ›  专栏  ›  技术社区  ›  Paul Suart Wes

为什么编译器会发现这一点不明确?

  •  2
  • Paul Suart Wes  · 技术社区  · 15 年前

    在我的基类中,我有一个泛型方法(理想情况下,这是一个属性,但不能有泛型属性)和一个非泛型属性,两者具有相同的名称:

    protected static T CurrentUserId<T>()
    {
        ...
    }
    
    protected static string CurrentUserId
    {
        get
        {
            ...
        }
    }
    

    然而,当我开始使用它们中的任何一个时,intellisense都会报告它们之间存在歧义。当然, base.CurrentUserId (没有paretesse)为编译器提供了足够的线索,我想调用非泛型属性?

    有人知道编译器为什么要处理这个问题吗?事先谢谢。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Ben McCormack    15 年前

    保罗关于“将仿制药引入混合体似乎完全掩盖了这个更基本的问题”的评论似乎是正确的。

    我相信您的问题与泛型的关系不大,更多的是与如何适当地重载一个方法有关(在这方面我可能是错的,但这是我从查找方法重载中收集到的)。我甚至不确定一个属性是否可以被同名的方法重载,但是不管怎样,让我们快速看看方法重载,它仍然应该演示为什么代码不能工作。

    您可以重载相同名称的方法(在您的情况下,名称为 CurrentUserId )如果方法的签名不同。签名包含以下四条信息:

    • 方法的名称
    • 参数个数
    • 参数的数据类型和顺序
    • 参数修饰符

    根据 插图C 2008 丹尼尔·索利斯

    “返回类型为 签名的一部分——尽管相信它是一个常见的错误。”

    让我们看一下您的属性和方法,看看根据上面提供的四条信息,它们是否具有相同的签名:

    • 方法的名称是否相同?对, 当前用户 .
    • 参数的数目是否相同?是的,0。
    • 参数的数据类型和顺序是否相同?两者都没有参数,所以是的。
    • 参数修饰符是否相同?同样,属性和方法都没有参数,所以是的,它们是相同的。

    从公式中删除参数时,唯一需要唯一标识类型的是它的名称。此外,由于方法(或属性)的返回类型不是其签名的一部分,因此一种类型是字符串,另一种类型是泛型并不重要。无论哪种方式,它们都有相同的签名(因为它们的名称相同,并且没有参数),编译器将无法适当地区分它们。

    尽管如此,我不确定这是否准确回答了你的问题(或者即使我正确地回答了这个问题……我很乐意接受评论中的更正,以进一步加深我的个人理解)。但是,我发现通过 第一 正确理解重载对于解决编译器如何处理代码的整体问题非常有帮助。

    我希望这有帮助。

        2
  •  9
  •   Rex M    15 年前

    括号没有提供足够的信息,因为您不总是使用它们。这就是为什么这行不通的原因:

    delegate T MyDelegate<T>();
    
    new MyDelegate(myClass.CurrentUserId)
    
    //are we talking about the method or the property?
    
        3
  •  5
  •   Henk Holterman    15 年前

    如果你不考虑仿制药,比如:

    public int Value { get;  set; }
    
    public int Value()
    {
        return 1;
    }
    

    你也会得到一个错误:类型…已包含值的定义

    我可以想到一个有明显冲突的案例:

    MyDelegate foo = new MyDelegate(Value);