Laurens Voncken
Laurens Voncken

Reputation: 235

How define a interface or class with a generic type who's generic type holds a generic type

I want to define a house having multiple (special and normal)rooms each having a collection of (special and normal)things.

I started using generics for my ThingCollection(and derived classes), but when I wanted to define my Room types I start having errors with my generic type defintions.

Does anyone know a proper way of defining my interfaces/classes so I won't get this error message?

Code:

namespace City.Street.House
{
    // Thing(s)
    public interface IThing{ }
    public interface ISpecialThing : IThing { }

    // Collection(s)
    public interface ThingCollection<TThing> where TThing : IThing { }
    public interface SpecialThingCollection<TThing> : ThingCollection<TThing> where TThing : ISpecialThing { }

    // Room(s)  // Error On TThing in both rows below:
    public interface Room<TThingCollection> where TThingCollection : ThingCollection<TThing> { } 
    public interface SpecialRoom<TThingCollection> : Room<TThingCollection> where TThingCollection : SpecialThingCollection<TThing> { }

    // House(s)
    public interface House { }
}

Error message:

CS0246: The type or namespace name 'TThing' could not be found (are you missing a using directive or an assembly reference?)

Upvotes: 0

Views: 40

Answers (2)

Laurens Voncken
Laurens Voncken

Reputation: 235

@Zohar Your well given answer made me refactor the code a little.

I used this part of your code:

// Room(s)
public interface Room<TThingCollection> where TThingCollection : ThingCollection<IThing> { }
public interface SpecialRoom<TThingCollection> : Room<TThingCollection> where TThingCollection : SpecialThingCollection<ISpecialThing> { }

Also I had to change the collections interfaces to this:

// Collection(s)
public interface ThingCollection<TThing> where TThing : IThing { }
public interface SpecialThingCollection<TSpecialThing> : ThingCollection<IThing> where  TSpecialThing : ISpecialThing{ }

Without these collection changes it wouldn't work.

Thanks for the help, much appreciated!

Upvotes: 0

Zohar Peled
Zohar Peled

Reputation: 82474

You can't use TThing as a type parameter in the generic constraint unless it's also defined in the method's signature as well - so Room<TThingCollection> should become Room<TThingCollection, TThing> - but for this to work you need to add more constraints:

public interface Room<TThingCollection<TThing>> 
    where TThingCollection : ThingCollection<TThing> 
    where TThing : IThing
{ }

public interface SpecialRoom<TThingCollection<TThing>> : Room<TThingCollection> 
    where TThingCollection : SpecialThingCollection<TThing> 
    where TThing : ISpecialThing
{ }

Or you can use the interfaces you've declared as the generic constraints (change TThing to IThing and ISpecialThing:

 // Room(s)
public interface Room<TThingCollection> where TThingCollection : ThingCollection<IThing> { }
public interface SpecialRoom<TThingCollection> : Room<TThingCollection> where TThingCollection : SpecialThingCollection<ISpecialThing> { }

Upvotes: 1

Related Questions