Вложенный класс со скрытым конструктором невозможен в c #? - PullRequest
8 голосов
/ 14 марта 2010

В последнее время я занимался программированием и столкнулся с проблемой, которая показалась мне странной в c #. (по крайней мере для меня)

public class Foo
{
    //whatever
    public class FooSpecificCollection : IList<Bar>
    {
         //implementation details
    }
    public FooSpecificCollection GetFoosStuff()
    {
         //return the collection
    }
}

Я хочу, чтобы потребитель Foo мог получить ссылку на FooSpecificCollection и даже выполнить некоторые операции с ней. Может быть, даже установить какое-либо другое свойство Foo или что-то в этом роде, но не для того, чтобы СОЗДАТЬ экземпляр этого класса. (единственный класс, который должен иметь возможность создавать эту коллекцию, должен быть Foo.

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

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

Это правильный способ справиться с такой ситуацией .?

Ответы [ 5 ]

4 голосов
/ 14 марта 2010

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

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

public class Foo
{
    public class FooSpecificCollection : List<Bar>
    {
         private FooSpecificCollection ()   { }

         public static FooSpecificCollection GetFoosStuff()
         {
            var collection = new FooSpecificCollection ();
            PrepareFooSpecificCollection(collection);
            return collection;            
         }
    }

    private static void PrepareFooSpecificCollection(FooSpecificCollection collection)
    {
         //prepare the collection
    }
}
4 голосов
/ 14 марта 2010

Сделайте ваш вложенный класс private и сделайте возвращаемое значение GetFoosStuff IList<Bar> вместо FooSpecificCollection.

Кроме того, есть хороший шанс, что , производное от List<Bar>ошибка .

3 голосов
/ 14 марта 2010

Если вы создаете библиотеку для использования другими, вы можете сделать конструктор internal. Любой, кто находится за пределами библиотеки, не сможет получить к ней доступ. Если вас беспокоит вызов конструктора в вашем собственном проекте, просто не вызывайте его вне родительского класса.

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

1 голос
/ 14 марта 2010

Есть решение, но я не думаю, что я бы использовал его в своем приложении :) Идея состоит в том, чтобы получить производный класс от FooSpecific, который является закрытым и может использоваться только внутри Foo, но имеет открытый конструктор, поэтому Foo может создавать его экземпляры.

public class Foo
{
    //whatever
    public class FooSpecific
    {
        // Protected contructor.
        protected FooSpecific()
        {
        }

        // All other code in here.
    }

    // Private helper class used for initialization.
    private class FooSpecificInitHelper : FooSpecific
    {
        public FooSpecificInitHelper()
        {
        }
    }

    // Method in foo to create instaces of FooSpecific.
    private FooSpecific CreateFooSpecific()
    {
        return new FooSpecificInitHelper();
    }
}
0 голосов
/ 14 марта 2010

Нет, и это не имеет смысла.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...