Что такое эквивалент С# для друга?

Возможный дубликат:
Почему С# не предоставляет ключевое слово друга стиля С++?

Я хотел бы, чтобы частные переменные-члены класса были доступны классу Tester, не подвергая их другим классам.

В С++ я просто объявляю класс Tester своим другом, как это сделать на С#? Может ли кто-нибудь дать мне пример?

Ответ 1

Нет прямого эквивалента "friend" - ближайшего доступного (и не очень близко) InternalsVisibleTo. Я использовал этот атрибут только для тестирования - там, где это очень удобно!

Пример: Для размещения в AssemblyInfo.cs

[assembly: InternalsVisibleTo("OtherAssembly")]

Ответ 2

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

class Outer
{
    class Inner
    {
       // This class can access Outer private members
    }
}

или если вы хотите поместить класс Inner в другой файл:

Outer.cs
partial class Outer
{
}


Inner.cs
partial class Outer
{
    class Inner
    {
       // This class can access Outer private members
    }
}

Ответ 3

Возьмите очень распространенный образец. Класс Factory делает Widgets. Класс Factory должен обманывать внутренности, потому что это Factory. Оба они реализованы в одном файле и по дизайну, желанию и природе тесно связаны классы - на самом деле, Widget на самом деле является только типом вывода из Factory.

В С++ сделайте Factory другом класса Widget.

В С#, что мы можем сделать? Единственное достойное решение, которое пришло мне в голову, - это придумать интерфейс IWidget, который только раскрывает общедоступные методы и имеет интерфейсы IWidget Factory.

Это включает в себя довольно много скуки - снова подвергая все естественные публичные свойства интерфейсу.

Ответ 4

В С# нет ключевого слова 'friend', но один параметр для проверки частных методов - использовать System.Reflection, чтобы получить дескриптор метода. Это позволит вам использовать частные методы.

Учитывая класс с этим определением:

public class Class1
{
    private int CallMe()
    {
        return 1;
    }
}

Вы можете вызвать его с помощью этого кода:

Class1 c = new Class1();
Type class1Type = c.GetType();
MethodInfo callMeMethod = class1Type.GetMethod("CallMe", BindingFlags.Instance | BindingFlags.NonPublic);

int result = (int)callMeMethod.Invoke(c, null);

Console.WriteLine(result);

Если вы используете Visual Studio Team System, вы можете заставить VS автоматически генерировать прокси-класс с закрытыми аксессуарами в нем, щелкнув правой кнопкой мыши метод и выбрав "Create Unit Tests..."

Ответ 5

Вы можете имитировать доступ к другу, если класс, которому дано право доступа, находится внутри другого пакета, и если методы, которые вы просматриваете, помечены как внутренние или внутренние, защищены. Вам необходимо изменить сборку, которую вы хотите предоставить, и добавить в AssemblyInfo.cs следующие параметры:

// Expose the internal members to the types in the My.Tester assembly
[assembly: InternalsVisibleTo("My.Tester, PublicKey=" +
"012700000480000094000000060200000024000052534131000400000100010091ab9" +
"ba23e07d4fb7404041ec4d81193cfa9d661e0e24bd2c03182e0e7fc75b265a092a3f8" +
"52c672895e55b95611684ea090e787497b0d11b902b1eccd9bc9ea3c9a56740ecda8e" +
"961c93c3960136eefcdf106955a4eb8fff2a97f66049cd0228854b24709c0c945b499" +
"413d29a2801a39d4c4c30bab653ebc8bf604f5840c88")]

Открытый ключ является необязательным, в зависимости от ваших потребностей.