Могут ли методы расширения C # получить доступ к закрытым переменным? - PullRequest
67 голосов
/ 10 октября 2009

Можно ли получить доступ к закрытым переменным объекта, используя метод расширения?

Ответы [ 7 ]

71 голосов
/ 10 октября 2009

Нет. Вы можете сделать то же самое в методе расширения, что и в «обычном» статическом методе в некотором служебном классе.

Так что этот метод расширения

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

эквивалентен некоторому статическому вспомогательному методу, подобному этому (по крайней мере, относительно того, к чему вы можете получить доступ):

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

(Конечно, вы могли бы использовать какое-то отражение в любом методе для доступа к закрытым членам. Но я думаю, что не в этом вопрос.)

22 голосов
/ 20 августа 2012

Нет, не может.

Однако вам будет интересно узнать, что другие ответы неверны, поскольку обычные статические методы не могут получить доступ к закрытым полям. Статический метод может получить доступ к закрытым нестатическим полям-членам в своем собственном классе. Следующий код совершенно допустим и показывает статический метод, обращающийся к закрытому полю:

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 приводит к хорошей компиляции кода. Причины этого обсуждаются здесь:

  1. Почему методы расширения разрешены только для не вложенных, неуниверсальных статических классов?
  2. Почему бы не разрешить определение метода Extension во вложенном классе?
11 голосов
/ 10 октября 2009
нет

Нет

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;
    }
}
3 голосов
/ 10 октября 2009

Нет, если вы не предоставляете какой-либо доступ к ним через публичные свойства или шаблон прокси.

2 голосов
/ 29 сентября 2017

Использовать отражение

Не рекомендуется, но вы можете получить доступ к любой закрытой переменной любого типа, используя другой метод расширения, например:

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");
2 голосов
/ 10 августа 2013

Если у вас есть класс, который вы расширяете, вы всегда объявляете его частичным, затем расширяете класс и имеете доступ ко всем закрытым членам в другом файле ... Но вы бы не использовали методы расширения .

0 голосов
/ 10 октября 2009

Метод расширения по сути является статическим методом, поэтому все, к чему у вас есть доступ, это открытые члены экземпляра, для которого метод расширения вызывается на

...