简体   繁体   English

C#-内部实例方法,为什么不使用类名就可以访问静态成员?

[英]C# - Inside instance method, why can we access static members without using the class name?

This seems counter-intuitive to me. 这对我来说似乎违反直觉。 If we have a class Dog with static method CountAllDogs(), C# forbids to call it like this: myDog.CountAllDogs(). 如果我们有一个具有静态方法CountAllDogs()的Dog类,则C#禁止这样调用它:myDog.CountAllDogs()。 (myDog is an object of type Dog). (myDog是Dog类型的对象)。 But if we are inside an instance method Bark(), we can call it simply by using CountAllDogs(). 但是,如果我们在实例方法Bark()中,则可以使用CountAllDogs()来简单地调用它。 Inside the instance method Bark(), the context ("this") is the object myDog, not the class itself, so I wonder why this is allowed? 在实例方法Bark()中,上下文(“ this”)是对象myDog,而不是类本身,所以我想知道为什么允许这样做吗?

"Why" questions are frequently vague, and this one is no exception. “为什么”的问题经常含糊不清,这一点也不例外。 Rather than answer your vague and confusing question, I'll answer a different question. 除了回答您的含糊和令人困惑的问题外,我将回答另一个问题。

What is the fundamental rule for resolving unqualified names in C#? 解决C#中不合格名称的基本规则是什么?

The fundamental rule of resolving an unqualified name is search from inside to outside . 解决不合格名称的基本规则是从内到外搜索 Suppose you have: 假设您有:

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 = ()=>{};

Now suppose somewhere inside H we have an unqualified name, X . 现在假设H内的某个地方有一个不合格的名称X We need to figure out what it means. 我们需要弄清楚这是什么意思。 So we go from inside to outside: 因此,我们从内到外:

  • Is there any local variable X? 是否有局部变量X? If yes, that's the meaning of X. If not... 如果是,那就是X的意思。
  • Is there any member of F called X? F中有没有一个叫X的成员?
  • Is there any member of D -- the base class of F -- called X? D的任何成员-F的基类-是否有X?
  • Is there any member of object -- the base class of D -- called X? 对象的任何成员-D的基类-是否有X?
  • Is there any member of B called X? B的成员中有X吗?
  • Is there any member of C -- which B is "using" -- called X? C的任何成员-B在“使用”的成员是否称为X?
  • Is there any member of A called X? A的任何成员都有X吗?
  • Is there any member of System called X? 系统中有没有称为X的成员?
  • Is there any global namespace called X? 是否有称为X的全局名称空间?

(This is a sketch that leaves out a few details, such as how aliases are dealt with and so on; read the specification if you want the details.) (这是一个草图,其中省略了一些细节,例如如何处理别名等;如果需要这些细节,请阅读规格。)

An interesting point here is that base classes are considered to be "more inside" than the lexically containing program element . 这里有趣的一点是, 基类被认为比词法包含的program元素“更内部” Members of D are considered to be members of F, so they must be checked before we check B. D的成员被认为是F的成员,因此检查B 之前必须先对其进行检查。

That's the fundamental rule. 这是基本原则。 There are also a few extra rules added for convenience. 为了方便起见,还添加了一些额外的规则。 For instance, if we had X() then only invocable members are considered when doing the search. 例如,如果我们有X()则在进行搜索时仅考虑可调用成员。 There is also the famous "Color Color" rule, which says that if you have a type called Color and a property of type Color called Color -- because what else would you call it? 还有一条著名的“颜色颜色”规则,该规则表示,如果您有一个名为Color的类型和一个名为Color的Color类型的属性,那么您还会调用它吗? -- then the name lookup rules for Color are smart about figuring out whether you meant the type or the property, even when that means departing from the fundamental rule of unqualified name lookup. -那么Color的名称查找规则很聪明,可以弄清楚您是指类型还是属性,即使这意味着脱离了不合格名称查找的基本规则。

Now that you know the fundamental rule you can apply it to your situation. 现在您已经知道了基本规则,可以将其应用于您的情况。 Why can you call a static member without qualification? 为什么您可以不加资格地致电静态会员? Because the fundamental rule of unqualified name lookup is "search from inside to outside", and doing so finds a static element with that name . 因为不限定名称查找的基本规则是“从内到外搜索”,所以查找具有该名称的静态元素 If we're inside H and we have G() then G is not a local but it is an invocable member of the enclosing class, so it wins. 如果我们在H并且有G()G不是局部变量,但它是封闭类的可调用成员,因此它赢了。 If we're inside H and we have E() then we find it in D , after failing to find it in H or F . 如果我们在H并且有E()那么在HF找不到它之后,就可以在D中找到它。 And so on. 等等。

When you call an unqualified instance member, same thing. 当您调用不合格的实例成员时,同样的事情。 The unqualified name is resolved, and if it turns out to be an instance member , then this is used as the receiver of the member. 解析了不合格的名称, 如果结果是实例成员 ,则将this用作该成员的接收者。

To call an instance-member you need an instance of course. 要调用实例成员,您当然需要一个实例。 In case you´re allready within an instance-member you can of course use the this -reference, which points to the current instance. 如果you're媒体链接的情况下,构件 ,当然你可以使用this引用,它指向当前实例。 If you´re on the other side calling your instance-member from outside your class you´d write something like this: 如果您从另一面从类外部调用实例成员,则应编写如下内容:

myInstance.DoSomething();

So actually using this as qualifier is redundant, you may simply omit it if you´re within the method. 因此, 实际上this用作限定符是多余的,如果您方法 ,则可以简单地忽略它。

A static member doesn´t know any instance, thus no this . 静态成员doesn't知道任何情况,因此没有this Adding the class´-name is again redundant information as adding the this -keyowrd to an instance-member. 再次添加类名是多余的信息,因为this -keyowrd添加到实例成员。

The compiler should be clever enough to determine that a member is static or not and thus if or of not he needs an instance. 编译器应该足够聪明,可以确定一个成员是否是静态的,从而确定他是否需要一个实例。

Personally I agree that adding the context in which a member might be invoked is a good thing, which is even forced in Java eg This avoids anoying prefixes on variables such as m_ for instance- and s_ for static members. 我个人同意,添加可以在其中调用成员的上下文是一件好事,这在Java中甚至是强制执行的,例如,这避免了烦恼诸如m_表示实例的前缀和s_表示静态成员的变量。 But again the compiler allready knows, it´s just a matter of taste. 但是,编译器已经知道了,这只是个问题。

So having said this there´s no actual need why this should or should not be permitted as it doesn´t avoid any mistakes not produces any. 所以说了这一点并没有实际的必要,为什么应该或不应该这样做,因为它不能避免任何错误,因此不会产生任何错误。 It´s just a convention-thing to be more strict. 这只是一个约定,要更加严格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么可以通过类实例在C#中的静态方法中调用非静态方法 - Why calling non-static method inside a static method in C# possible via class instance C# 为什么我可以通过属性访问非 static 类的方法和属性,而无需先创建该 class 的实例? - C# Why can I access a non static class' methods and properties via a property, without creating an instance of that class first? C# - 调用扩展方法而不限定类名、实例方法语法与静态语法 - C# - calling extension method without qualifying with class name, instance method syntax vs static syntax 为什么我们不能从实例对象访问静态成员? - why we cannot access static members from instance object? 为什么我可以使用类名而不是类实例来调用这个静态方法? - Why can I call this static method using the class name but not using a class instance? C#是否可以将Class类型作为参数传递给Function并访问方法内部的类变量 - C# Can we pass Class type as parameter to Function and access class variables inside method 为什么我不能在静态类中拥有实例成员但是我可以在静态方法中拥有实例成员? - Why can I not have instance members in a static class but I can have instance members in a static methods? 每个继承的类的C#静态实例成员 - C# Static instance members for each inherited class 无法在C#中的静态类中声明实例成员 - Cannot declare instance members in a static class in C# C#使用类内部的方法创建类实例 - c# create class instance using method inside class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM