这对我来说似乎是违反直觉的。如果我们有一个带有静态方法CountAllDogs()的类Dog,C#禁止这样调用它:myDog.CountAllDogs()。 (myDog是Dog类型的对象)。 但是如果我们在实例方法Bark()中,我们可以通过使用CountAllDogs()来调用它。在实例方法Bark()中,上下文(“this”)是对象myDog,而不是类本身,所以我想知道为什么允许这样做?
答案 0 :(得分:6)
“为什么”这些问题经常含糊不清,而且这个问题也不例外。我会回答一个不同的问题,而不是回答你模糊而混乱的问题。
在C#中解析不合格的名称的基本规则是什么?
解决不合格名称的基本规则是从内到外搜索。假设你有:
using System;
namespace A {
namespace B {
using C;
class D
{
public static void E() {}
}
class F : D {
public static void G() {}
public void H()
{
Action i = ()=>{};
现在假设H
内的某个地方有一个不合格的名字X
。我们需要弄清楚它意味着什么。所以我们从内到外:
(这是一个草图,省略了一些细节,例如如何处理别名等等;如果你想要详细信息,请阅读规范。)
这里有一个有趣的观点是,基类被认为比含有词法的程序元素更“内部”。 D的成员被认为是F的成员,所以在我们检查B之前必须检查。
这是基本规则。为方便起见,还添加了一些额外的规则。例如,如果我们有X()
,那么在进行搜索时只会考虑可调用的成员。还有着名的“颜色颜色”规则,它表示如果你有一个名为Color的类型和一个名为Color的Color类型的属性 - 因为你还有什么叫它呢? - 然后,Color的名称查找规则很明智,无论是否意味着您的类型或属性,即使这意味着偏离了非限定名称查找的基本规则。
现在您已了解基本规则,您可以将其应用于您的情况。为什么你可以没有资格打电话给静态会员?因为非限定名称查找的基本规则是“从内到外搜索”,并且这样做找到具有该名称的静态元素。如果我们在H
内,并且我们有G()
,那么G
不是本地的,但它是封闭类的可调用成员,因此它获胜。如果我们在H
内,并且我们E()
,那么我们会在D
或H
中找不到它后在F
找到它。等等。
当您调用不合格的实例成员时,同样的事情。解析了非限定名称,如果结果是实例成员,则,然后this
用作成员的接收者。
答案 1 :(得分:1)
要调用实例成员,您需要一个实例。如果您已经在实例成员中,您当然可以使用this
- 引用,它指向当前实例。如果你在另一边从你的课外调用你的实例成员,你会写下这样的东西:
myInstance.DoSomething();
所以实际使用this
作为限定符是多余的,如果你在方法中,你可以简单地省略它。
静态成员不知道任何实例,因此没有this
。添加class'-name再次是将this
- keyowrd添加到实例成员的冗余信息。
编译器应该足够聪明,以确定成员是否是静态的,因此他是否需要实例。
我个人同意添加可以调用成员的上下文是一件好事,甚至在Java中强制使用,例如这样可以避免对变量(如m_
例如 - 和s_
)的静态成员使用前缀。但是编译器已经知道了,这只是一个品味问题。
所以说这没有实际的需要为什么这应该或不应该被允许,因为它不会避免任何错误而不会产生任何错误。这只是一个更严格的惯例。