【问题标题】:Can C# extension methods access private variables?C# 扩展方法可以访问私有变量吗?
【发布时间】:2009-10-10 16:02:40
【问题描述】:

是否可以使用扩展方法访问对象的私有变量?

【问题讨论】:

    标签: c# extension-methods


    【解决方案1】:

    没有。您可以在扩展方法中执行与在某些实用程序类中的“普通”静态方法中相同的操作。

    所以这个扩展方法

    public static void SomeMethod(this string s)
    {
        // do something with 's'
    }
    

    相当于一些像这样的静态辅助方法(至少关于您可以访问的内容):

    public static void SomeStringMethod(string s)
    {
        // do something with 's'
    }
    

    (当然,您可以在任一方法中使用一些反射来访问私有成员。但我想这不是这个问题的重点。)

    【讨论】:

    • +1。顺便说一句,您可以拥有私有扩展方法; odetocode.com/Blogs/scott/archive/2009/10/05/… 上有一篇很好的文章。扩展方法也可以访问其静态实用程序类的私有静态成员。
    • 即使这被标记为 C#,这也适用于任何提供扩展方法支持的 .NET 语言。
    • @TrueWill - 但由于它们必须是静态的、非嵌套的、非泛型类型,它们不能真正拥有对任何 object 的 变量的私有访问权。 internal 访问,当然 - 但不是 private
    【解决方案2】:

    不可以。

    但是,您将有兴趣知道其他答案是不正确的,即普通静态方法无法访问私有字段。 静态方法可以访问自己类中的私有非静态成员字段。以下代码完全有效,显示了访问私有字段的静态方法:

    public class Foo
    {
        private bool _field;
    
        public static bool GetField(Foo foo)
        {
            return foo._field;
        }
    }
    

    现在...回到您的问题。您可能认为扩展方法应该能够做同样的事情,因为(不存在的)与其他答案声称存在的静态方法“等价”。但是,您不能在嵌套类中声明扩展方法。因此,如果您尝试执行以下操作:

    public class Foo
    {
        private bool _field;
    
        public static class Extensions
        {
            public static bool GetField(this Foo foo)
            {
                return foo._field;
            }
        }
    }
    

    你会得到一个编译错误提示

    扩展方法必须定义在顶级静态类中; Extensions 是一个嵌套类

    请注意,有趣的是,删除 this 关键字会导致代码编译正常。原因在这里讨论:

    1. Why are extension methods only allowed in non-nested, non-generic static class?
    2. Why not allow Extension method definition in nested class?

    【讨论】:

      【解决方案3】:

      没有:

      public class Foo
      {
          private string bar;
      }
      
      public static class FooExtensions
      {
          public static void Test(this Foo foo)
          {
              // Compile error here: Foo.bar is inaccessible due to its protection level  
              var bar = foo.bar;
          }
      }
      

      【讨论】:

        【解决方案4】:

        使用反射

        不推荐,但您可以使用其他扩展方法访问任何类型的任何私有变量,如下所示:

        public static T GetFieldValue<T>(this object obj, string name) {
            var field = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            return (T)field?.GetValue(obj);
        }
        

        然后访问任意类型的私有字段:

        Foo foo = new Foo();
        string privateBar = foo.GetFieldValue<string>("_bar");
        

        【讨论】:

        • 这应该是首选答案。
        【解决方案5】:

        不,除非您通过公共属性或代理模式授予对它们的某种访问权限。

        【讨论】:

          【解决方案6】:

          如果您拥有要扩展的类,则始终可以声明该类的部分,然后扩展该类并可以访问不同文件中的所有私有成员...但是您实际上不会使用扩展方法.

          【讨论】:

            【解决方案7】:

            扩展方法本质上是一个静态方法,因此您只能访问调用扩展方法的实例的公共成员

            【讨论】:

              猜你喜欢
              • 2013-05-20
              • 1970-01-01
              • 2011-07-30
              • 2010-10-03
              • 1970-01-01
              • 2021-11-24
              • 1970-01-01
              • 1970-01-01
              • 2011-06-10
              相关资源
              最近更新 更多