簡體   English   中英

C#-內部實例方法,為什么不使用類名就可以訪問靜態成員?

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

這對我來說似乎違反直覺。 如果我們有一個具有靜態方法CountAllDogs()的Dog類,則C#禁止這樣調用它:myDog.CountAllDogs()。 (myDog是Dog類型的對象)。 但是,如果我們在實例方法Bark()中,則可以使用CountAllDogs()來簡單地調用它。 在實例方法Bark()中,上下文(“ this”)是對象myDog,而不是類本身,所以我想知道為什么允許這樣做嗎?

“為什么”的問題經常含糊不清,這一點也不例外。 除了回答您的含糊和令人困惑的問題外,我將回答另一個問題。

解決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 我們需要弄清楚這是什么意思。 因此,我們從內到外:

  • 是否有局部變量X? 如果是,那就是X的意思。
  • F中有沒有一個叫X的成員?
  • D的任何成員-F的基類-是否有X?
  • 對象的任何成員-D的基類-是否有X?
  • B的成員中有X嗎?
  • C的任何成員-B在“使用”的成員是否稱為X?
  • A的任何成員都有X嗎?
  • 系統中有沒有稱為X的成員?
  • 是否有稱為X的全局名稱空間?

(這是一個草圖,其中省略了一些細節,例如如何處理別名等;如果需要這些細節,請閱讀規格。)

這里有趣的一點是, 基類被認為比詞法包含的program元素“更內部” D的成員被認為是F的成員,因此檢查B 之前必須先對其進行檢查。

這是基本原則。 為了方便起見,還添加了一些額外的規則。 例如,如果我們有X()則在進行搜索時僅考慮可調用成員。 還有一條著名的“顏色顏色”規則,該規則表示,如果您有一個名為Color的類型和一個名為Color的Color類型的屬性,那么您還會調用它嗎? -那么Color的名稱查找規則很聰明,可以弄清楚您是指類型還是屬性,即使這意味着脫離了不合格名稱查找的基本規則。

現在您已經知道了基本規則,可以將其應用於您的情況。 為什么您可以不加資格地致電靜態會員? 因為不限定名稱查找的基本規則是“從內到外搜索”,所以查找具有該名稱的靜態元素 如果我們在H並且有G()G不是局部變量,但它是封閉類的可調用成員,因此它贏了。 如果我們在H並且有E()那么在HF找不到它之后,就可以在D中找到它。 等等。

當您調用不合格的實例成員時,同樣的事情。 解析了不合格的名稱, 如果結果是實例成員 ,則將this用作該成員的接收者。

要調用實例成員,您當然需要一個實例。 如果you're媒體鏈接的情況下,構件 ,當然你可以使用this引用,它指向當前實例。 如果您從另一面從類外部調用實例成員,則應編寫如下內容:

myInstance.DoSomething();

因此, 實際上this用作限定符是多余的,如果您方法 ,則可以簡單地忽略它。

靜態成員doesn't知道任何情況,因此沒有this 再次添加類名是多余的信息,因為this -keyowrd添加到實例成員。

編譯器應該足夠聰明,可以確定一個成員是否是靜態的,從而確定他是否需要一個實例。

我個人同意,添加可以在其中調用成員的上下文是一件好事,這在Java中甚至是強制執行的,例如,這避免了煩惱諸如m_表示實例的前綴和s_表示靜態成員的變量。 但是,編譯器已經知道了,這只是個問題。

所以說了這一點並沒有實際的必要,為什么應該或不應該這樣做,因為它不能避免任何錯誤,因此不會產生任何錯誤。 這只是一個約定,要更加嚴格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM