Как создать конструктора, который только применим определенным классом. (Друг C++, эквивалентный в c#)

Насколько я знаю в C#, нет никакой поддержки "друга" ключевого слова как в C++. Существует ли альтернативный способ разработать класс, который мог достигнуть этого того же конечного результата, не обращаясь к недоступному "другу" ключевое слово?

Для тех, кто уже не знает, Друг, ключевое слово позволяет программисту определять, что к члену класса "X" может получить доступ и использовать только класс "Y". Но к любому другому классу участник кажется частным, таким образом, к ним нельзя получить доступ. Класс "Y" не должен наследоваться классу "X".

11
задан 7wp 6 January 2010 в 22:20
поделиться

9 ответов

Нет, на C# этого сделать нельзя.

Одним из распространенных обходных путей является создание объекта, для которого вы хотите спрятать конструктор на интерфейсе. Затем вы можете использовать другой объект, чтобы построить приватный, вложенный класс, реализующий этот интерфейс, и вернуть его через Factory. Это не позволит внешнему миру построить ваш объект напрямую, так как они всегда видят и взаимодействуют только с интерфейсом.

public interface IMyObject
{
     void DoSomething();
}

public class MyFriendClass
{
     IMyObject GetObject() { return new MyObject(); }

     class MyObject : IMyObject
     {
          public void DoSomething() { // ... Do something here
          }
     }
}
10
ответ дан 3 December 2019 в 05:12
поделиться

Как насчет того, чтобы explicity реализовал интерфейс, который виден только определенному классу?

Что-то вроде:

public void IFreindOfX.Foo() //This is a method in the class that's a 'friend' to class X.
{
   /* Do Stuff */
}

, а затем убедился, что IFriendOfX виден классу X. В классе X вы бы вызвали метод, сначала приведя X к IFriendOfX, а затем вызвали бы Foo(). Другое преимущество заключается в том, что он достаточно самооформляется... то есть, он довольно близок к тому, чтобы иметь само ключевое слово "друг".

2
ответ дан 3 December 2019 в 05:12
поделиться

А как насчет создания частного класса? Это именно то, что вы, кажется, описываете. К члену класса X можно получить доступ и использовать только класс Y , а для любого другого класса он кажется частным, поскольку, ну, он является частным:

public class Y
{
   private class X { }

   private X Friend;

   public Y()
   {
      Friend = new X();
   }
}
2
ответ дан 3 December 2019 в 05:12
поделиться

Насколько я знаю, Внутреннее ключевое слово является самым близким в .NET. Этот вопрос прольет больше света на Internal: Внутренний в C#

1
ответ дан 3 December 2019 в 05:12
поделиться

Единственное, о чем я могу думать, что это было бы даже близко, это защищенная внутренняя , но это не ограничивает ее определенным классом. Единственный приятель, о котором я знаю на c# - это дружеская сборка. Но это не ограничивает его определенным классом.

Единственное, что я могу придумать, чтобы попытаться сделать это, это сделать что-то вроде следующего:

public class A
{
   public A() {}
   protected internal A(B b) {}
}

public class B
{
   A myVersion;

   public B() 
   {
      myVersion = A(this);
   }
}

Единственный другой способ, который я могу придумать, это сделать что-то вроде инъекции конструктора, используя отражение, которое делается внутри вашего класса-другая сборка. Механизм инъекции позволил бы ограничить его до желаемого, но может быть очень громоздким. Взгляните на что-нибудь вроде Spring.Net для некоторых возможностей инъекции.

1
ответ дан 3 December 2019 в 05:12
поделиться

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

Например, если конструктор Class1 должен быть вызван Class2:

public Class1()
{
    string callingClass = new StackFrame(1).GetMethod().DeclaringType.Name;

    if (callingClass != "Class2")
    {
        throw new ApplicationException(
            string.Concat("Class1 constructor can not be called by ",
            callingClass, "."));
    }
}

EDIT:

Пожалуйста, обратите внимание, что на самом деле я бы никогда не сделал этого в "реальном" коде. Технически это работает, но это довольно неприятно. Я просто подумал, что это творческий подход. :)

1
ответ дан 3 December 2019 в 05:12
поделиться

Вы можете получить доступ к приватным членам/методам с помощью Reflection.

Так как в нем есть дизайнерский тег, мне никогда особо не нравилось ключевое слово "друг". Оно пробивает инкапсуляцию, и это всегда казалось мне грязным.

0
ответ дан 3 December 2019 в 05:12
поделиться

Это немного пахнет. Есть и множество других способов добиться реализации, скрывающихся в C#. Ограничение конструкции только конкретными классами не достигает всего этого.

Не могли бы вы предоставить дополнительную информацию о цели этого требования? Как уже было сказано, внутреннее наиболее близко подходит для ограничения доступности к классу. В зависимости от цели есть способы построить его поверх этого.

0
ответ дан 3 December 2019 в 05:12
поделиться

Нет. Ближайший из имеющихся у вас - внутренний конструктор или частный конструктор и отдельный фабричный метод (вероятно, внутренний , так что вы мало что сэкономили).

2
ответ дан 3 December 2019 в 05:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: