tags:

views:

57

answers:

4

Maybe a confusing title, what I'm after is a class, which only has certain amount of instantiations. Still confused?

What I'm actually after is a list of star ratings(none, half, one, one and a half) etc. So I need a class (or maybe a struct?) which has two fields, value and string representation (for now anyway, leading to other fields; url of image etc). And I need a container for these, a List, ObservColl, IEnumerable, just something to contain them.

But I don't want the class to be instantiable by anything, except the container object, but still have the class available as a type to set as a field on another class.

Is this possible? Or am I going to have to sacrifice something along the way?

+3  A: 

I hope this is what you want:

Make the class public or internal (as you need it), but the constructor private:

public class MyClass
{
    private MyClass() { }
}

Then create a public or internal static method in the class to get your list:

public class MyClass
{
    // ...
    public static List<MyClass> GetList()
    {
        List<MyClass> list = new List<MyClass>();
        list.Add(new MyClass());
        // ...
        return list;
    }
}

You can now only get a list via this method. List<MyClass> a = MyClass.GetList(); If you want you can implement it with a static property and privat static field, too:

public class MyClass
{
    // ...
    static MyClass()
    {
        myList = new List<MyClass>();
        myList.Add(new MyClass());
        // ...
    }
    private static List<MyClass> myList = null;
    public static List<MyClass> MyList
    {
        get { return myList; }
    }
}
Hinek
Would be my solution too. Leaves the question: what is the plural form of 'singleton'?
Henk Holterman
@Henk an enumerated type
Pete Kirkham
Return an immutable value from MyList (eg IEnumerable<MyClass>), and probably don't bother with the lazy initialisation - making it thread safe it will add complexity.
Pete Kirkham
Thanks Pete, I changed the initialisation. I did not change List to IEnumerable, because I think it depends on what he wants to do with it.
Hinek
A: 

The access level of a constructor can be set to the following:

  • Public (complete access)
  • Internal (only from classes within the same namespace)
  • Protected (only from itself and derived classes)
  • Private (only from itself)

The closest thing you could do to achieve what you mean is create a new namespace containing only your "container" class and your "star rating" class, and make the star rating constructor internal.

Still, if you (or someone else) were to extend that namespace, the constructor would be available to all members of the namespace.

Matteo Mosca
+1  A: 
public interface IInnerType
{
    Int32 Id { get; set; }
}

public class Container
{
    public Container()
    {
        Items = new InnerTypeCollection();
        Items.Add(new InnerType() { Id = 1 });
        Items.Add(new InnerType() { Id = 2 });
        Items.Add(new InnerType() { Id = 3 });
        Items.Add(new InnerType() { Id = 4 });
        Items.Add(new InnerType() { Id = 5 });
    }

    public InnerTypeCollection Items { get; protected set; }

    class InnerType : IInnerType
    {
        public InnerType()
        { }

        public Int32 Id { get; set; }
    }

    public class InnerTypeCollection : ICollection<IInnerType>
    {
        List<IInnerType> Items { get; set; }

        public InnerTypeCollection()
        {
            Items = new List<IInnerType>();
        }

        public void Add(IInnerType item)
        {
            if (!(item is InnerType))
            {
                throw new ArgumentException("item must be of InnerType");
            }
            Items.Add(item);
        }

        public void Clear()
        {
            Items.Clear();
        }

        public bool Contains(IInnerType item)
        {
            return Items.Contains(item);
        }

        public void CopyTo(IInnerType[] array, int arrayIndex)
        {
            Items.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return Items.Count; }
        }

        public bool IsReadOnly
        {
            get { return (Items as ICollection<IInnerType>).IsReadOnly; }
        }

        public bool Remove(IInnerType item)
        {
            return Items.Remove(item);
        }

        public IEnumerator<IInnerType> GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }
    }
}
decyclone
Only `Container` class will be able to create instances of `InnerType` and the custom collection restricts any additions that are not `InnerType`.
decyclone
A: 

Expose the Star Rating as an interface from the container and have a Factory on the container for returning concrete implementation(s)?

Daz Lewis