MoonKnight
MoonKnight

Reputation: 23833

Generic Constraints Syntax and Usage

Suppose I want to author a generic Max method which returns the maximum of two values. I can utilize the generic interface IComparable<T>: [null checks ignored]

static T Max<T>(T x, T z) where T : IComparable<T>
{
    return x.CompareTo(z) > 0 ? x : z;
}

fine. Now the first thing I don't get is the following extension to the above example:

static void Initialize<T>(T[] array) where T : new()
{ 
    for (int i = 0; i < array.length; i++)
        array[i] = new(T);
}

where would it be neccessary to adopt this syntax (new() in this context is confusing me here)? Moreover, I have seen the following generic template that befuddles me even further

class GenericClass<T> where T : SomeClass, Interface
                                      where U : new()
{ /* Some Code */ }

Here I assume that T is a type constraint that is filtered from the type constraint U. So if this is the case then we could write

class Magic<T>
{
    Magic<U> SomeOtherClass<U>() where U : T { /* Some Code */ }
}

do I have this right and how many levels of this sort of hierarchy is possible in C#?

Upvotes: 3

Views: 133

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500105

Well, you've given an example of where the new() constraint is useful: if you want to populate an array with "new" objects, each of which is created by calling the parameterless constructor.

As for this:

class GenericClass<T> where T : SomeClass, Interface
                                  where U : new()

... that won't compile, as it's trying to constrain U, but that's not declared as a type parameter.

But your Magic<T> will compile, and will force U to be appropriately compatible with T. (The exact details are tricky; see the specification.)

For example, you could call

new Magic<Stream>.SomeOtherClass<FileStream>()

or

new Magic<IFormattable>.SomeOtherClass<int>()

Upvotes: 4

Related Questions