8

I' ve been doing some programming lately and faced an issue which i found weird in c#. (at least for me)

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

I want the consumer of Foo to be able to obtain a reference to FooSpecificCollection, even perform some operations on it. Maybe even set it to some other property of Foo or smth like that, but not To be able to CREATE an instance of this class. (the only class that should be able to instatiate this collection should be Foo.

Is my request really that far-fetched? I know that people way smarter defined c# but shouldn't there be such an option that a parent class can create a nested class instance but nobody else can't.

So far I created a solution to make an abstract class, or interface available through the property and implement a concrete private class that is not available anywhere else.

Is this a correct way to handle such a situation.?

3
  • possible duplicate : stackoverflow.com/questions/1664793/… Commented Mar 14, 2010 at 2:34
  • Curious : is it the case there will be multiple instances of 'Foo, each with its own unique 'FooSpecificCollection ? Commented Mar 14, 2010 at 9:23
  • Yes, that's the case. Let's say every client will have a Foo instance (it will be created by factory at some precise time) and Foo will create a FooSpecificCollection for itself. I give access to foo specific collection so that people know what foo has in it, and I let them play with the items, but they should not be able to create one as it makes little sense. During the night I thought maybe I try to make this code with too much semantics:) Commented Mar 14, 2010 at 9:41

5 Answers 5

4

The way embedded classes work is that they, as members of the outer class, get access to private members of that outer class. But not the other way around (what is what you want).

You can shield the constructor of FooSpecificCollection, but then the Factory has to be part of FooSpecificCollection itself. It could enlist the outer class:

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
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

probably You are right:) it resembles the factory pattern a lot (I thought about it actually).
Always learn something from your answers, thanks, Henk. In this case what happens if there are multiple instances of 'Foo ?
@BillW, if you really were to use this pattern you would probably have to pass an instance of Foo through GetFooStuff() and on to PrepareFooSpecificCollection().
4

Make your nested class private and make the return value of GetFoosStuff IList<Bar> instead of FooSpecificCollection.

Also, there's a good chance that deriving from List<Bar> is a bug.

4 Comments

I derive from a List<Bar> not foo
sorry I meant IList of course. List would be the internal implementation. But that is not what the question is about. But thanks for vigilance:)
Just curious what you mean by "deriving from List<Foo> is a bug". I looked at the link, but can't find anything that indicates a problem in deriving from List<T> in itself.
99% of the time when you are claiming something is a List<T>, what you're actually trying to say is that it's an enumeration of T (IEnumerable<T>). It works, but is bad design to be too specific in the return type.
3

If you are creating a library for others to use, you could make the constructor internal. Anyone outside the library will not be able to access it. If you are concerned about calling the constructor in your own project, just don't call it outside the parent class.

We create classes all the time which are not directly related to other classes, but the constructors don't have to be hidden from non-related classes. We (the programmers) know the the objects are not related so we don't ever create an instance of one in the other.

Comments

1

There is a solution but I don't think I would use it in my App :) The idea is to have derived class from FooSpecific which is private and can be used only inside Foo but has public constructor, so Foo can create its instances.

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();
    }
}

Comments

0

No, and it doesn't really make sense.

I mean the whole point is so that you could potentially return other instances; but who will be deriving from that class anyway? Certainly not any other classes (Because that would be wrong, and imply it shouldn't be hidden inside the main class), so ...

3 Comments

I want to have some functionality in nested class that is clear and concise to read and use (ex nice interface on some internal collection of FOO). And I don't want to let people create that class. Of course they should have no business in that anyway, but I still would like a clear semantics that say - this class helps you operate on some Foo's stuff, but Foo gives it too you and you should not create it on your own... Internal is ok in a assembly but I don't get Your answer why it does not make sens. I want a developer using my class not to try instantiate it... why is that senseless?
There are other concerns than derived classes here.
luckyluke: So make the constructor private? I thought you were trying to stop the outer class making an instance of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.