这个内部类静态范围魔法如何工作?

时间:2012-02-27 14:32:43

标签: c# static scope

public class Outer
{
    public  class Inner
    {
        public static string OtherValue { get { return SomeValue; } }
    }

    public static string SomeValue { get { return "Outer"; } }
}

为什么以上编译? SomeValue是否超出了Inner的范围,需要使用Outer.SomeValue进行限定?上面的内容与下面的内容基本相同(不会编译)?

public class Outer
{
    public class Inner
    {
        public static string OtherValue { get { return Outer.SomeValue; } }
    }

    public static string SomeValue { get { return "Outer"; } }
}

这里发生了什么static魔法?

4 个答案:

答案 0 :(得分:7)

就像:

public class Super
{
    public class Sub
    {
        public static string OtherValue { get { return Super.SomeValue; } }
    }

    public static string SomeValue { get { return "Outer"; } }
}

Super持有静态SomeValue

<小时/> 它更清晰地显示如下:

public class Super
{
    public static string SomeValue { get { return "Outer"; } }
}

public class Sub
{
    public static string OtherValue { get { return Super.SomeValue; } }
}

现在,SubSuperpublic,其共享范围内的所有人都可以看到其静态属性。正如@jonskeet指出的那样,编译器将首先搜索SomeValue查找类Sub的最佳值,因为该值在该类中使用。

现在这样的事情无法编译:

public class Super
{
    private static string SomeValue { get { return "Outer"; } }
}

public class Sub
{
    public static string OtherValue { get { return SomeValue; } }
}

然而,

public class Super
{
    private static string SomeValue { get { return "Outer"; } }

    public class Sub
    {
        public static string OtherValue { get { return SomeValue; } }
    }
}

由于类的嵌套,上述情况很好。

答案 1 :(得分:2)

Sub是Super的嵌套类,因此Super的任何成员都在Sub的范围内。但是,这些“继承”成员不是Sub的成员,因此Sub.SomeValue无效。编译器将SomeValue转换为Super.SomeValue

答案 2 :(得分:2)

这与简单名称的含义有关,这由C#4规范第7.6.2节规定:

  

否则对于每个实例类型T(第10.3.1节),从直接封闭类型声明的实例类型开始,并继续每个封闭类或结构声明的实例类型(如果有):

     
      
  • ...
  •   
  • 否则,如果具有K类型参数的I中的I成员查找(第7.4节)产生匹配:   
        
    • [...此处不适用...]
    •   
    • [...此处不适用...]
    •   
    • 否则,结果与T.I [...]
    • 形式的成员访问(第7.6.4节)相同   
  •   

换句话说,编译器首先检查Sub.SomeValue是否有效,发现它是否有效,然后检查Super.SomeValue,然后查找它。

答案 3 :(得分:1)

内部类继承外部类范围的一部分。因此,Outer中的成员可以从Sub内访问,但它们仍然属于外部类,这就是Sub.SomeValue不起作用的原因。

技术术语是词法范围,它意味着变量的范围涵盖了它所处的“词汇”块,也就是说,它可以在源代码块中的任何位置访问它。无论运行时所有权如何,都包括子块。另见:https://en.wikipedia.org/wiki/Scope_%28programming%29#Lexical_scoping

Javascript,Lisp,Haskell等语言以及大多数其他针对函数式编程的语言都广泛使用词法范围,它与其他FP概念密切相关,如部分函数应用,闭包和currying。

一旦你习惯了它,它就会成为一个非常有用(优雅)的工具。