C#扩展方法可以访问私有变量吗?

Geo*_*Geo 68 c# extension-methods

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

M4N*_*M4N 72

不可以.您可以在扩展方法中执行与在某些实用程序类中的"普通"静态方法相同的操作.

所以这个扩展方法

public static void SomeMethod(this string s)
{
    // do something with 's'
}
Run Code Online (Sandbox Code Playgroud)

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

public static void SomeStringMethod(string s)
{
    // do something with 's'
}
Run Code Online (Sandbox Code Playgroud)

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

  • +1.另外,您可以使用私有扩展方法; http://odetocode.com/Blogs/scott/archive/2009/10/05/private-extension-methods.aspx上有一篇很好的文章,扩展方法也可以访问其静态实用程序类的私有静态成员. (3认同)
  • 尽管这被标记为C#,但这适用于任何支持扩展方法的.NET语言. (3认同)
  • @ZaidMasud - 它说它与"在某个实用程序类中"的静态方法相同,而不是在同一个类中. (2认同)

Zai*_*sud 23

不,它不能.

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

public class Foo
{
    private bool _field;

    public static bool GetField(Foo foo)
    {
        return foo._field;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Foo
{
    private bool _field;

    public static class Extensions
    {
        public static bool GetField(this Foo foo)
        {
            return foo._field;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您将收到编译错误说明

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

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

  1. 为什么扩展方法只允许在非嵌套的非泛型静态类中使用?
  2. 为什么不在嵌套类中允许扩展方法定义?


Dar*_*rov 11

没有:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Bru*_*ell 7

使用反射

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

Foo foo = new Foo();
string privateBar = foo.GetFieldValue<string>("_bar");
Run Code Online (Sandbox Code Playgroud)