In this post, I am going to discuss about Generic Classes and bit more on this. Just for a smooth start:
“Generics were introduced in .NET 2.0, which provides us a way to create Classes/Methods/Types and many more without specifying the specific type of parameters. Parameters must be provided at the time of creating the instances. So we can say Generics are only a blueprint/templated version and actual type is defined at Runtime.”
So let's first create a simple Class, say Point
:
public class Point<T>
{
}
Here as you can see, I have created a generic class Point
, its coordinates X
and Y
can be of any type.
So in this post, I am going to mainly discuss Constraint with generics.
It's very imperative to have a Generic Class, which can accept any type of parameter. But sometimes, one might require that your generic Class can be instantiated with only specific types. Like say, you want that a Generic can be instantiated with only say a Class Point Type or of its derived types. Is it possible?
Yes this is possible.
And also, C# provides a very robust way to implement this feature. So using it, it can be very helpful at certain times to define a constraint over Generic.
So what are the ways to do this. We’ll first take a few examples then. Later, we will conclude.
So first, how can we define constraint with Generics. It is done using where
clause.
We have two types of variables in C# - reference and Value..
No…
Now we have three types:
- Reference
- Value
- Nullable (It has features of both types)
So we’ll discuss about Nullable type in some other post. Let’s stick to constraint in Generic type. So what will you do if you want to have Generic type that can be instantiated as Value type. Do we need to make a comma separated list of all the possible value types.
NO...
We know, in C#, a Class
is a reference type and Struct
is a value type. So we can define a generic that will be instantiated of Value
type only. Like here, my Point
class could be one real time example that can be instantiated to a Value Type. It can be done as:
public class Point
where T1 : struct
{
...
}
Similarly, If we want a generic that can be of Reference type only, that can be just opposite to the above one.
Public Class Queue: where T:Class
{
}
You also can have multiple restrictions. You can put a comma separated list. So how can you do this? It can be like:
public class Point
where T1 : class
{
...
}
But what is meant by whether T
would follow all or anyone of them. It should follow all, like here T
must implement all three interfaces, IEnumerable
, IList
, IDisposable
.
There are few restrictions on this. While providing multiple restrictions, it can contains only one class but it can have multiple interfaces. Also, there are some restrictions on ordering of the types. The class
or struct
keyword should come first and if Class/Struct is there, it requires to be written ahead of All. And after this, any class or base class, then all other Interfaces.
We can also have multiple restrictions on a Generic Type, but it should not be conflicting. Like we can never say:
Public class Point where T: struct, class
{
...
}
It’ll be a compile time error.
So one more constraint we can have like:
Public class Point where T: new()
{
...
}
So what it means here is that T
must be a type that has a parameter less constructor. I can have parameterized but it also must have parameterless one also. It can also be accompanied with other restriction as well. but this should be last in the list.
Similarly, you can apply constraint on those Generic Types that have multiple parameters. Like my below one:
public class Point
where T1 : class, new()
where T2 : IList
{
...
}
Here also, you have the option to apply the constraint to any one of them or both of them or some of them.
I think that’s all about Generic constraint.
One thing you might wonder is whether the following is possible:
public class Point
where T1 : int
{
...
}
But this is not possible. The constraint must be an interface, a non-sealed class or a type.
When you will compile, you will get an ERROR “A type used as a constraint must be an interface, a non-sealed class or a type”.
I was thinking about having this one as well, but not there. But you might except it in the coming version of C#.
Hope you all must have liked this. Do share your feedback.
Cheers,
Brij