views:

136

answers:

5

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.?

+2  A: 

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.

Zach Johnson
A: 

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 ...

Noon Silk
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 assemblybut 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?
luckyluke
There are other concerns than derived classes here.
Henk Holterman
luckyluke: So make the constructor private? I thought you were trying to stop the outer class making an instance of it.
Noon Silk
+3  A: 

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.

280Z28
I derive from a List<Bar> not foo
luckyluke
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:)
luckyluke
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.
Zach Johnson
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.
Yuliy
A: 

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();
    }
}
Andrew Bezzub
+2  A: 

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
    }
}
Henk Holterman
probably You are right:) it resembles the factory pattern a lot (I thought about it actually).
luckyluke
Always learn something from your answers, thanks, Henk. In this case what happens if there are multiple instances of 'Foo ?
BillW
@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().
Henk Holterman