I came across the following code, all in a single file/class. I'm leaving out the details, its the construct I'm interested in. Why are there two different declarations for the same class and how are they different? What's the purpose of the syntax for the second declaration?
public abstract class MyClass
{
...
}
public abstract class MyClass<TMyClass> : MyClass
where TMyClass: MyClass<TMyClass>
{
...
}
In mathematics, the tilde often represents approximation, especially when used in duplicate, and is sometimes called the "equivalency sign." In regular expressions, the tilde is used as an operator in pattern matching, and in C programming, it is used as a bitwise operator representing a unary negation (i.e., "bitwise ...
C programming language uses blocks to separate pieces of code performing different tasks. This helps make programming easier and keeps the code clean. Thus, the code is easy to understand even for those who are starting out. C is used in embedded programming, which is used to control micro-controllers.
MyClass
- A abstract class named MyClass.
MyClass<TMyClass> : MyClass
- A abstract generic class named MyClass<>
but with a generic type named TMyClass
.
If you rename the types, it will be easier to see:
public abstract class MyBaseClass
{
...
}
public abstract class MyClass<T> : MyBaseClass
where T: MyClass<T>
{
...
}
Types with different generic arity (i.e. number of generic type parameters, which can be zero or more) are considered as completely unrelated by the language and can have the same name.
This means that you can have classes Foo
, Foo<T>
and Foo<T,U>
at the same time; the syntax will allow the compiler to determine which you are referring to. You can see this happen in the base framework which includes Action
, Action<T>
etc.
The "recursive" construct class C<T> where T: C<T>
(the inheritance from a non-generic C
does not change anything so I removed it) is the C# on what is called the Curiously Recurring Template Pattern (CRTP) in C++. Eric Lippert has covered this subject very well in a blog post, where the conclusion is that one should think more than twice before implementing this -- there are problems it can solve, but the solution also has a price.
public abstract class MyClass<TMyClass> : MyClass
where TMyClass: MyClass<TMyClass>
{
...
}
is a class that inherits from MyClass
, and it takes a generic type, which has to inherit from MyClass<TMyClass>
Here's a simpler example of the same thing for you
public static void Main()
{
MyClass<Myclass> other = new MyClass<Myclass>(new Myclass());
List<int> intlist = new List<int>();
}
public class Myclass
{
public Myclass()
{
}
public int i { get; set; }
}
public class MyClass<T> where T : Myclass
{
T value;
public MyClass(T val)
{
value = val;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With