Inherit from a generic base class, apply a constraint, and implement an interface in C#

83,509

Solution 1

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

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

Solution 2

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.

Solution 3

public interface IFoo {}
public interface IBar {}

public class ParentFoo<T,T1> { }
public class DerivedFoo<T, T1> : ParentFoo<T, T1>, IFoo where T1 : IBar { }

Solution 4

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.

Share:
83,509
Dan Rigby
Author by

Dan Rigby

I'm a passionate software developer who helps people create by building tools and services for developers that spark joy.

Updated on September 20, 2021

Comments

  • Dan Rigby
    Dan Rigby over 2 years

    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.

    • nurisezgin
      nurisezgin about 5 years
      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.
  • Dan Rigby
    Dan Rigby over 14 years
    Eric, while I greatly respect you as a professional and appreciate your feedback, I can't help but be frustrated by what comes across as an abrasive answer. You are criticizing me for choosing to ask a question on a programming Q&A site over locating, downloading, and searching through a highly technical 503 page Word document buried off a link in MSDN. Thats pretty rough. This was the most efficient use of my time and has the added benefit that it may help someone else later. The link to the C# Lang Spec for those interested is: msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
  • Eric Lippert
    Eric Lippert over 14 years
    No criticism was intended. There is a pervasive bias in pure-text communication which makes simple statements of facts sound brusque and abrasive; I try to read charitably when presented with a list of helpful facts, and recommend that you do so as well. I stand by my recommendation; if you have questions about syntax, the spec answers them definitively and begins with a helpful table of contents for locating definitions of specific syntaxes.
  • SolutionYogi
    SolutionYogi over 14 years
    Dan, finding C# spec is as simple as entering 'C# Spec' in Google and hitting the 'I am lucky' button. And if you are a professional C# developer, you should already have C# spec in PDF format on your machine. Also, I don't mean to criticize you either. I was not used to reading spec earlier but I have started reading it thanks to Jon, Eric and Pavel who always quotes C# spec for any question. I found that C# spec, even though it could be hard to read at times, is a great way to learn about the language.
  • Dan Rigby
    Dan Rigby over 14 years
    @Eric Lippert: Fair enough. Thank you for your reply. As a constructive suggestion, it would be helpful if Microsoft would integrate the contents of the specification directly into MSDN in addition to having it exist as a separate download. The Visual Studio .Net MSDN version has an integrated version of the specification, but not later versions. I've given thought to purchasing Anders Hejlberg's book, but with .Net 4.0 around the corner I'm reluctant to just yet. amazon.com/C-Programming-Language-3rd/dp/0321562992 Thanks.
  • Dan Rigby
    Dan Rigby over 14 years
    @SolutionYogi: The document on MS's website is in .doc format (I'm aware of it's location as I linked to it in my comment), where have you located a PDF version? Thanks.
  • SolutionYogi
    SolutionYogi over 14 years
  • Dan Rigby
    Dan Rigby over 14 years
    @SolutionYogi: The only catch to that is that the ECMA standard trails the Microsoft C# language specification in currency. For example, ECMA-334 does not cover LINQ or Lambdas. While it would have worked for my question, I'm more inclined to reference the most current document.
  • SolutionYogi
    SolutionYogi over 14 years
    You are absolutely correct. So far, for my simple needs, the PDF version has worked.
  • Adam Robinson
    Adam Robinson over 14 years
    Wow, you learn something every day...didn't know that a class definition could be followed by a semicolon (don't know why you'd want to, but I'm sure there's a reason). +1
  • Eric Lippert
    Eric Lippert over 14 years
    C++ requires that a class declaration end in a semicolon. Many C# developers come from a C++ background; sometimes their fingers put the semicolon in without their brains getting involved. :-) There are a number of constructs in C# which take an optional semi where C++ requires one. It's pretty much just a subtle convenience. I suppose it also lets you subtly call out when a type declaration is ending vs say a method body declaration.
  • Andy V
    Andy V over 7 years
    To others, I've internalized this as, a class only gets one where clause, and it goes at the end for any & all generic type constraints.
  • bwing
    bwing about 6 years
    @Visser It is allowed to have multiple where clauses, class Test<T1,T2> where T1 : Interface1 where T2 : Interface2
  • v01pe
    v01pe over 5 years
    @Visser yeah, what bwing said, also each where clause can have multiple constraints… so the syntax from the original post is correct, it just means something different that the op wanted. where T2 : IBar, IFoo just means that T2 has to implement both interfaces instead of DerivedFoo<T1,T2> implementing IFoo