簡體   English   中英

C#變量范圍不一致?

[英]C# variable scoping not consistent?

在變量范圍方面,C#非常適合挑選。 它怎么可能接受這個代碼:

class Program
{
    int x = 0;

    void foo()
    {
        int x = 0;
        x = 1;

        Console.WriteLine(x);
    }
}

如果你問我,這是一個明顯的命名沖突。 編譯器(VS 2010)仍然接受它。 為什么?

C#名稱隱藏的規則非常復雜。 該語言允許你提到的情況,但不允許許多類似的情況。 看到

http://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/

有關這個復雜主題的一些信息。

為了解決您的具體問題:編譯器當然可以檢測到該沖突。 事實上,它確實發現了這種沖突:

class P
{
    int x;
    void M()
    {
        x = 123; // The author intends "this.x = 123;"
        int x = 0;
    }
}

等效的C ++程序將是合法的C ++,因為在C ++中,局部變量在聲明時就進入了范圍。 在C#中,局部變量在整個塊中都在范圍內,並且在聲明之前使用它是非法的。 如果你嘗試編譯這個程序,你會得到:

error CS0844: Cannot use local variable 'x' before it is declared.
The declaration of the local variable hides the field 'P.x'.

請參閱: 本地聲明隱藏該字段 編譯器知道它。 那么為什么在你的情況下隱藏一個字段不是錯誤

讓我們假設為了論證它應該是一個錯誤。 這也應該是一個錯誤嗎?

class B
{
    protected int x;
}
class D : B
{
    void M()
    {
        int x;
    }
}

字段x是來自B的繼承的D的成員 。所以這也應該是一個錯誤,對吧?

現在假設您有這個由Foo Corporation制作的程序:

class B
{
}

這個程序由Bar Corporation制作:

class D : B
{
    void M()
    {
        int x;
    }
}

編譯。 現在假設Foo Corp更新他們的基類並向您發送新版本:

class B
{
    protected int x;
}

您告訴我包含名為x的局部變量的每個派生類現在都無法編譯?

那太可怕了。 我們必須允許局部變量來影響成員。

如果我們要允許本地人影響基類的成員,那么不允許本地人影響類的成員就顯得非常奇怪。

這不是命名沖突:在C#中,局部變量優先於具有相同名稱的實例變量,因為它們的范圍更窄。

當編譯器匹配名稱聲明的名稱引用時,它使用具有最窄范圍的匹配聲明

有關該主題的詳細信息,請參閱參考匹配文檔。

這是正常的。

在構造函數中,我經常使用相同的。

public Person(string name) {
  this.name = name;
}

否則,不可能聲明名為成員變量的方法參數。

C#4.0規范說明了通過嵌套隱藏范圍:

3.7.1.1通過嵌套隱藏

由於在類或結構中嵌套類型以及作為參數和局部變量聲明的結果,在命名空間內嵌套命名空間或類型的結果可能會發生通過嵌套隱藏的名稱。 在示例中

class A {
    int i = 0;
    void F() {
        int i = 1;
    }
    void G() {
        i = 1;
    }
}

在F方法中,實例變量i被局部變量i隱藏,但在G方法中,我仍然引用實例變量。

當內部作用域中的名稱隱藏外部作用域中的名稱時,它會隱藏該名稱的所有重載出現。

在示例中

class Outer {
    static void F(int i) {}
    static void F(string s) {}
    class Inner
    {
        void G() {
            F(1);           // Invokes Outer.Inner.F
            F("Hello");     // Error
        }
        static void F(long l) {}
    }
}

調用F(1)調用在Inner中聲明的F,因為F的所有外部出現都被內部聲明隱藏。 出於同樣的原因,調用F(“Hello”)會導致編譯時錯誤。

沒有命名沖突。 編譯器始終采用nearest /最小范圍變量。

在這種情況下,那就是你在foo聲明的x變量。 每個變量都可以以特定方式訪問,因此沒有命名沖突。

如果要訪問外部x,可以使用this.x

因為規則是如果局部變量和類成員之間存在沖突,則局部變量具有更高的優先級。

這不是模糊的,本地將是假定在您的函數中進行重新定義的變量。 如果你需要獲取類變量this.x允許名稱解析。

暫無
暫無

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

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