拡張メソッドを使用してオブジェクトのプライベート変数にアクセスすることは可能ですか?
いいえ。いくつかのユーティリティクラスの「通常の」静的メソッドと同じように、拡張メソッドで行うことができます。
したがって、この拡張メソッド
public static void SomeMethod(this string s)
{
// do something with 's'
}
このような静的ヘルパーメソッドと同等です(少なくともアクセスできるものに関して):
public static void SomeStringMethod(string s)
{
// do something with 's'
}
(もちろん、どちらの方法でもリフレクションを使用してプライベートメンバーにアクセスできます。しかし、これはこの質問のポイントではないと思います。)
いいえ、できません。
ただし、通常の静的メソッドはプライベートフィールドにアクセスできないという他の答えが間違っていることを知りたいと思うでしょう。 静的メソッドは、独自のクラスの非静的メンバーフィールドにアクセスできます。次のコードは完全に有効で、静的フィールドにアクセスする静的メソッドを示しています。
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;
}
}
}
コンパイルエラーが表示されます
拡張メソッドはトップレベルの静的クラスで定義する必要があります。拡張機能はネストされたクラスです
興味深いことに、this
キーワードを削除すると、コードが正常にコンパイルされることに注意してください。この理由は次のとおりです。
番号:
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;
}
}
いいえ、パブリックプロパティまたはプロキシパターンを介して何らかのアクセスを許可しない限り。
推奨されませんが、次のような別の拡張メソッドを使用して、任意のタイプのプライベート変数にアクセスできます。
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");
拡張するクラスを所有している場合は、常にクラスを部分的に宣言し、クラスを拡張して別のファイルのすべてのプライベートメンバーにアクセスできます。しかし、実際には拡張メソッドを使用しません。
拡張メソッドは基本的に静的メソッドであるため、アクセスできるのは、拡張メソッドが呼び出されるインスタンスのパブリックメンバーだけです。