tags:

views:

171

answers:

3

This code compiles but looks very strange. I have a typical and simple parent/child relationship here which is implemented using generics in a very strange way. But I can't seem to find any other way of doing it.

class SampleObject<T> //I don't want to make this a generic but am forced to
{
  //The SampleContainer this object is in
  //This must be located in this base class
  public SampleContainer<T> Parent { get; set; }
}

class SpecificObject : SampleObject<SpecificObject>
//SampleObject<SpecificObject> !!? This is the bizzare bit
//It seems really strange but necessary for compilation to work
{
}


//A class to contain a List of objects derived from SampleObjects
class SampleContainer<T>
{
  public List<T> List;
}


class Start
{
  public void Test()
  {
    SampleContainer<SpecificObject> container = new SampleContainer<SpecificObject>();

    SpecificObject o = new SpecificObject(); //create an object
    container.List.Add(o); //add it to the list
    o.Parent = container; //set its parent
  }
}

Can this code be simplified?

+1  A: 

In the MSDN documentation, it states that:

When deriving from a generic base class, you must provide a type argument instead of the base-class's generic type parameter:

public class BaseClass<T>
{...}
public class SubClass : BaseClass<int>
{...}

It's probably a constraint that the C# designers set up in the compiler. They require that a derived type must specify the type of the generic argument at compile time. I'm not quite sure why.

Robert Harvey
A: 

Generics can create some unwieldy class hierarchies. However, the syntax for SpecificObject : SampleObject does make sense, since you're stating that the object has a parent relationship. The only other way I could see you do this, would be to split out the hierarchy with an interface. It doesn't buy much, but it may help clarify the intent.

interface IHasParent<T>
{
     T Parent { get; set; }
}

public class SpecificObject : IHasParent<SpecificObject>
{
    public SpecificObject Parent { get; set; }
}

If you're concerned about how verbose your collection is, you can tame the angle brackets a bit by using:

public SpecificObjectContainer : Container<SpecificObject>
{
}
bryanbcook
+3  A: 

This seems to work without the type.

Is this what you were looking for?

class SampleObject //I don't want to make this a generic but am forced to
    {

        //The SampleContainer this object is in
        //This must be located in this base class
        public SampleContainer<SampleObject> Parent;//{ get; set; }
    }

    class SpecificObject : SampleObject
    //SampleObject<SpecificObject> !!? This is the bizzare bit
    //It seems really strange but necessary for compilation to work
    {
    }


    //A class to contain a List of objects derived from SampleObjects
    class SampleContainer<T>
    {
        public List<T> List;
    }


    class Start
    {
        public void Test()
        {
            SampleContainer<SampleObject> container = new SampleContainer<SampleObject>();

            SpecificObject o = new SpecificObject(); //create an object
            container.List.Add(o); //add it to the list
            o.Parent = container; //set its parent
        }
    }
astander
This is the answer! Doh!! Just need to check my question was the question :-)
Petras