+1  A: 

The way you are using it makes no sense at all. But using a generic parameter in a constraint on that same parameter is quite normal, here's a more obvious example:

class MySortedList<T> where T : IComparable<T>

The constraint expresses the fact that there must be an ordering between objects of type T in order to put them into sorted order.

EDIT: I'm going to deconstruct your second example, where the constraint is actually wrong but helps it compile.

The code in question is:

/*analogous method for comparison*/
public static List<T> AddNullItem<T>(this List<T> list, bool value) 
    where T : List<T>
{
    list.Add(null);
    return list;
}

The reason it won't compile without a constraint is that value types can't be null. List<T> is a reference type, so by forcing where T : List<T> you force T to be a reference type which can be null. But you also make AddNullItem nearly useless, since you can no longer call it on List<string>, etc. The correct constraint is:

/* corrected constraint so the compiler won't complain about null */
public static List<T> AddNullItem<T>(this List<T> list) 
    where T : class
{
    list.Add(null);
    return list;
}

NB: I also removed the second parameter which was unused.

But you can even remove that constraint if you use default(T), which is provided for exactly this purpose, it means null when T is a reference type and all-zero for any value type.

/* most generic form */
public static List<T> AddNullItem<T>(this List<T> list) 
{
    list.Add(default(T));
    return list;
}

I suspect that your first method also needs a constraint like T : class, but since I don't have all the classes you're using I can't say for certain.

Ben Voigt
I agree about the making no sense, but it compiles and does what I want it to. Your example is too simple to capture the use case.
Simon Francesco
Sorry I hit enter, I meant to continue... I am thinking of a List<T> where I could have a list of bananas and have an extension method such as list.AddNullItem() so the generic parameter, is itself generic.
Simon Francesco
I hope the additional information I added will help you to see why it didn't compile without the constraint, but the constraint is not necessarily correct.
Ben Voigt
Thanks for your efforts Ben, I appreciate it, I think on balance I should remove the analogy, because it does not drive at the issue I am trying to solve. I also knew at the time that the primitive vs object issue might cloud the question. I am going to edit my original question to do this.
Simon Francesco
A: 

I can only guess what the code you've posted does. That said, I can see merit in a generic type constraint such as this. It would make sense (to me) in any scenario where you want an argument of some type that can perform certain operations on arguments of the same type.

Here's an unrelated example:

public static IComparable<T> Max<T>(this IComparable<T> value, T other)
    where T : IComparable<T>
{
    return value.CompareTo(other) > 0 ? value : other;
}

Code like this would allow you to write something like:

int start = 5;
var max = start.Max(6).Max(3).Max(10).Max(8); // result: 10

The namespace FluentHtml is what should sort of tip you off that this is the intention of the code (to enable the chaining of method calls).

Dan Tao
+4  A: 

The reason constraint is there is because TextInput type itself has such a constraint like so.

public abstract class TextInput<T> where T: TextInput<T>{
   //...
}

Also note that TextInput<T> is abstract and the only way to make an instance of such class is to derive from it in a CRTP-like fashion:

public class FileUpload : TextInput<FileUpload> {
}

The extension method will not compile without that constraint, that's why it's there.

The reason for having CRTP in the first place is to enable strongly typed methods enabling Fluent Interface on the base class, so consider such example:

public abstract class TextInput<T> where T: TextInput<T>{
   public T Length(int length) {
      Attr(length); 
      return (T)this;
   }
}
public class FileUpload : TextInput<FileUpload> {
   FileUpload FileName(string fileName) {
      Attr(fileName);
      return this;
   }
}

So when you have a FileUpload instance, Length returns an instance of FileUpload, even though it's defined on the base class. This makes the following syntax possible:

FileUpload upload = new FileUpload();
upload                      //FileUpload instance
 .Length(5)                 //FileUpload instance, defined on TextInput<T>
 .FileName("filename.txt"); //FileUpload instance, defined on FileUpload

EDIT To address OP's comments about recursive class inheritance. This is a well known pattern in C++ called Curiously Recurring Template Pattern. Have a read of it here. Up until today I didn't know it was possible in C#. I suspect that constraint has something to do with enabling the use of this pattern in C#.

Igor Zevaka
Igor I think your comment about the type inheriting from a constrained type is getting is part of the issue that it won't compile without the constraint. But my real question is about the syntax though, where T seems to refer to the both the type and the constraint ie both TextInput of T and T itself which seems ambiguous.
Simon Francesco
Thanks just had a read of the CRTP. Chuckle, my example has a 'this is by design' type feel, in the sense that you can define circularity as unintended recursion, or in this case what looks like circularity is really recursion. It also shows how hard it is to become fluent in a given programming language :)
Simon Francesco
Haha, i was chucking at you using the term fluent. That is very appropriate here as this pattern is known as Fluent Interface (method chaining).
Igor Zevaka
A: 
public static TextInput<T> ReadOnly<T>(this TextInput<T> element, bool value)
    where T: TextInput<T>

Let's break it down:

TextInput<T> is the return type.

TextInput<T> is the type being extended (the type of the first parameter to the static method)

ReadOnly<T> is the name of the function that extends a type whose definition includes T, i.e. TextInput<T>.

where T: TextInput<T> is the constraint on T from ReadOnly<T>, such that T can be used in a generic TextInput<TSource>. (T is TSource!)

I don't think it's circular.

If you take out the constraint, I would expect that element is trying to be casted to the generic type (not a TextInput of the generic type), which is obviously not going to work.

Jeff Meatball Yang
Hi Jeff, You have all the same assumptions as I do except we draw different conclusions. It feels circular to me because using mathematical or logical substition the constraint implies that we should be able to do something like this: ReadOnly<T> where T : TextInput<T> => ReadOnly<TextInput<T>> where T : TextInput<T> => ReadOnly<TextInput<TextInput<T>>> .... rinse and repeat ad infinitum :).
Simon Francesco
Hi Simon, if you think of `where T: TextInput<T>` as just saying, "where T is the generic part of TextInput", it should click. Hopefully. :)
Jeff Meatball Yang
In other words, don't read the where clause as logical substitution. It's not. It's meant to define how T is related to another object, which is more like composition rather than substitution.
Jeff Meatball Yang
Sorry Jeff, but that constraint means "`T` is a subclass of (inherits from) `TextInput<T>`"
Ben Voigt
+4  A: 

This is legal, it is not circular, and it is fairly common. I personally dislike it.

The reasons I dislike it are:

1) It is excessively clever; as you've discovered, clever code is hard for people unfamiliar with the intricacies of the type system to intuitively understand.

2) It does not map well to my intuition of what a generic type "represents". I like classes to represent categories of things, and generic classes to represent parameterized categories. It is clear to me that a "list of strings" and a "list of numbers" are both kinds of lists, differing only in the type of the thing in the list. It is much less clear to me what "a TextInput of T where T is a TextInput of T" is. Don't make me think.

3) This pattern is frequently used in an attempt to enforce a constraint in the type system which is actually not enforcable in C#. Namely this one:

abstract class Animal<T> where T : Animal<T>
{
    public abstract void MakeFriends(IEnumerable<T> newFriends);
}
class Cat : Animal<Cat>
{
    public override void MakeFriends(IEnumerable<Cat> newFriends) { ... }
}

The idea here is "a subclass Cat of Animal can only make friends with other Cats."

The problem is that the desired rule is not actually enforced:

class Tiger: Animal<Cat>
{
    public override void MakeFriends(IEnumerable<Cat> newFriends) { ... }
}

Now a Tiger can make friends with Cats, but not with Tigers.

To actually make this work in C# you'd need to do something like:

abstract class Animal 
{
    public abstract void MakeFriends(IEnumerable<THISTYPE> newFriends);
}

where "THISTYPE" is a magical new language feature that means "an overriding class is required to fill in its own type here".

class Cat : Animal 
{
    public override void MakeFriends(IEnumerable<Cat> newFriends) {}
}

class Tiger: Animal
{
    // illegal!
    public override void MakeFriends(IEnumerable<Cat> newFriends) { ... }
}

Unfortunately, that's not typesafe either:

Animal animal = new Cat();
animal.MakeFriends(new Animal[] {new Tiger()});

If the rule is "an animal can make friends with any of its kind" then an animal can make friends with animals. But a cat can only make friends with cats, not tigers! The stuff in the parameter positions has got to be valid contravariantly; in this hypothetical case we'd be requiring covariance, which isn't going to work.

I seem to have digressed somewhat. Returning to the subject of this curiously recurring pattern: I try to only use this pattern for common, easily understood situations like the ones mentioned by other answers:

class SortedList<T> where T : IComparable<T>

That is, we need every T to be comparable to every other T if we have any hope of making a sorted list of them.

To actually be flagged as circular there has to be a bona-fide circularity in dependencies:

class C<T, U> where T : U where U : T

An interesting area of type theory (that at present the C# compiler handles poorly) is the area of non-circular but infinitary generic types. I have written an infinitary type detector but it did not make it into the C# 4 compiler and is not a high priority for possible hypothetical future versions of the compiler. If you're interested in some examples of infinitary types, or some examples of where the C# cycle detector messes up, see my article on that:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx

Eric Lippert
Thanks Eric, it is an interesting area. I have a few other questions around constraints but I guess I should post them as another question :-).
Simon Francesco