139
votes

This is a syntax question. I have a generic class which is inheriting from a generic base class and is applying a constraint to one of the type parameters. I also want the derived class to implement an interface. For the life of me, I cannot seem to figure out the correct syntax.

This is what I have:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar { ... }

The first thing that came to mind was this:

DerivedFoo<T1,T2> : ParentFoo<T1, T2> where T2 : IBar, IFoo { ... }

But that is incorrect as that causes T2 to need to implement both IBar and IFoo, not DerivedFoo to implement IFoo.

I've tried a bit of Googling, use of colons, semicolons, etc, but I've turned up short. I'm sure the answer is head slappingly simple.

4
I couldn't understand @Adam's answer when I looked once but after 2mins I could get what it is, thank you for the answer. Derived class has more than one implementation may be this is the point. Anyway I want to show its notation for others. "class DerivedClass<Type> : ParentClass where Type : IType" . Nothing should be between last implemented class and where clause.nurisezgin

4 Answers

203
votes

You include the entire signature of your class before you define generic constraints.

class DerivedFoo<T1, T2> : ParentFoo<T1, T2>, IFoo where T2 : IBar
{
    ...
}
17
votes

My recommendation: when you have a question about the syntax of the C# language, read the specification; that's why we publish it. You'll want to read section 10.1.

To answer your specific question, the order of things in a class declaration is:

  • attributes, in square brackets
  • modifiers ("public", "static", and so on)
  • "partial"
  • "class"
  • the class name
  • a comma-separated list of type parameter declarations inside angle brackets
  • a colon followed a comma-separated list of base types (base class and implemented interfaces, base class must go first if there is one)
  • type parameter constraints
  • the body of the class, surrounded by braces
  • a semicolon

Everything on that list is optional except for "class", the name, and the body, but everything must appear in that order if it appears.

10
votes
public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }
1
votes
public class KeyAndValue<T>
{
    public string Key { get; set; }
    public virtual T Value { get; set; }
}

public class KeyAndValue : KeyAndValue<string>
{
    public override string Value { get; set; }
}

This is an extension off the existing answers. It defaults to string if you don't supply a type. I didn't implement an interface but that shouldn't require anything different than usual.