Können C # -Erweiterungsmethoden auf private Variablen zugreifen?

73

Ist es möglich, mit einer Erweiterungsmethode auf die privaten Variablen eines Objekts zuzugreifen?

Geo
quelle

Antworten:

74

Nein. Sie können in einer Erweiterungsmethode dasselbe tun wie in einer "normalen" statischen Methode in einigen Dienstprogrammklassen.

Also diese Erweiterungsmethode

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

entspricht einer statischen Hilfsmethode wie dieser (zumindest in Bezug auf das, worauf Sie zugreifen können):

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

(Natürlich können Sie in beiden Methoden einige Überlegungen anstellen, um auf private Mitglieder zuzugreifen. Aber ich denke, das ist nicht der Punkt dieser Frage.)

M4N
quelle
4
+1. Nebenbei können Sie private Erweiterungsmethoden verwenden. Es gibt einen schönen Artikel dazu unter odetocode.com/Blogs/scott/archive/2009/10/05/… Erweiterungsmethoden können auch auf private statische Mitglieder ihrer statischen Dienstprogrammklasse zugreifen.
TrueWill
3
Obwohl dies als C # gekennzeichnet ist, gilt dies für alle .NET-Sprachen, die Erweiterungsmethoden unterstützen.
Scott Dorman
1
@TrueWill - aber da es sich um statische, nicht verschachtelte, nicht generische Typen handeln muss, können sie nicht wirklich privaten Zugriff auf die Variablen eines Objekts haben . internalZugang, sicher - aber nicht private.
Marc Gravell
-1 Ich verstehe die positiven Stimmen hier nicht ... diese Antwort ist sehr irreführend. Eine normale öffentliche statische Methode kann auf eine private Methode innerhalb der Klasse zugreifen, eine Erweiterungsmethode jedoch nicht . Der folgende Code ist vollkommen gültig und wird kompiliert: public class Foo {private bool _variable; public static bool GetVariable (Foo foo) {return foo._variable; }}
Zaid Masud
2
@ZaidMasud - Es heißt, es ist dasselbe wie eine statische Methode "in einer Utility-Klasse", nicht in derselben Klasse.
Lee
22

Nein, ich kann nicht.

Sie werden jedoch interessiert sein zu wissen, dass die anderen Antworten falsch sind, wenn gesagt wird, dass normale statische Methoden nicht auf private Felder zugreifen können. Eine statische Methode kann auf private nicht statische Mitgliedsfelder in ihrer eigenen Klasse zugreifen. Der folgende Code ist vollkommen gültig und zeigt eine statische Methode, die auf ein privates Feld zugreift:

public class Foo
{
    private bool _field;

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

Nun ... zurück zu Ihrer Frage. Sie könnten denken, dass eine Erweiterungsmethode in der Lage sein sollte, dasselbe zu tun, da (nicht vorhandene) "Äquivalenz" zu statischen Methoden besteht, von denen andere Antworten behaupten, dass sie existieren. Sie können jedoch keine Erweiterungsmethoden innerhalb einer verschachtelten Klasse deklarieren. Wenn Sie also Folgendes versuchen:

public class Foo
{
    private bool _field;

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

Sie erhalten einen Kompilierungsfehler

Die Erweiterungsmethode muss in einer statischen Klasse der obersten Ebene definiert werden. Extensions ist eine verschachtelte Klasse

Interessanterweise führt das Entfernen des thisSchlüsselworts dazu, dass der Code ordnungsgemäß kompiliert wird. Die Gründe hierfür werden hier diskutiert:

  1. Warum sind Erweiterungsmethoden nur in nicht verschachtelten, nicht generischen statischen Klassen zulässig?
  2. Warum nicht die Definition der Erweiterungsmethode in einer verschachtelten Klasse zulassen?
Zaid Masud
quelle
11

Nein:

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;
    }
}
Darin Dimitrov
quelle
6

Verwenden Sie Reflexion

Nicht empfohlen, aber Sie können möglicherweise mit einer anderen Erweiterungsmethode wie folgt auf jede private Variable eines beliebigen Typs zugreifen:

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);
}

Und dann auf ein privates Feld eines beliebigen Typs zugreifen:

Foo foo = new Foo();
string privateBar = foo.GetFieldValue<string>("_bar");
Bruno Zell
quelle
Dies sollte die bevorzugte Antwort sein.
ぐ イ き ん
3

Nein, es sei denn, Sie gewähren ihnen Zugriff über öffentliche Eigenschaften oder ein Proxy-Muster.

Yuriy Faktorovich
quelle
2

Wenn Sie die Klasse besitzen, die Sie erweitern, deklarieren Sie die Klasse immer als Teil, erweitern Sie die Klasse und haben Zugriff auf alle privaten Mitglieder in einer anderen Datei ... Aber Sie würden nicht wirklich Erweiterungsmethoden verwenden.

Rimbimbambo
quelle
0

Eine Erweiterungsmethode ist im Wesentlichen eine statische Methode. Sie haben also nur Zugriff auf die öffentlichen Mitglieder der Instanz, für die die Erweiterungsmethode aufgerufen wird

Abhijeet Patel
quelle