开发者

Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates? [duplicate]

开发者 https://www.devze.com 2022-12-13 00:45 出处:网络
This question already has answers here: Inheritance on a constrained generic type parameter (3 answers)
This question already has answers here: Inheritance on a constrained generic type parameter (3 answers) Closed 9 years ago.

Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates? I mean I know it impossible because CLR does not support this, but why?

I am aware of the profound differences between C++ templates and C# generics - the former are compile time entities and must be resolved during the compilation, while the latter are first class run-time entities.

Still, I am failing to see the reason why CLR designers did not come up with a scheme which would ultimately enable a CLR generic type to derive from one of its generic type parameters. After all, this would be tremendously useful feature, I personally miss it greatly.

EDIT:

I would like to know of a hard-core issue, fixing which yields such a high price on implementing this feature that justifies it not being implemented yet. For instance, examine this fictional declaration:

class C<T> : T
{
}

As Eric Lippert has noticed what if "What if T is a struct? What if T is a sealed class type? What if T is an interface type? What if T is C?! What if T is a class dervied from C? What if T is an abstract type with an abstract method? What if T has less accessibility than C ? What if T is System.ValueType? (Can you have a non-struct which inherits from System.ValueType?) What about System.Delegate, System.Enum, and so on?"

As Eric continues, "Those are the easy, obvious on开发者_C百科es". Indeed, he is right. I am interested in a concrete example of some neither easy nor obvious issue, which is hard to resolve.


Well, start by asking yourself what could possibly go wrong with class C<T> : T { }. A huge number of things come immediately to mind:

What if T is a struct? What if T is a sealed class type? What if T is an interface type? What if T is C<T>?! What if T is a class derived from C<T>? What if T is an abstract type with an abstract method? What if T has less accessibility than C ? What if T is System.ValueType? (Can you have a non-struct which inherits from System.ValueType?) What about System.Delegate, System.Enum, and so on?

Those are the easy, obvious ones. The proposed feature opens up literally hundreds, if not thousands of more subtle questions about the interaction between the type and its base type, all of which would have to be carefully specified, implemented and tested. We'd undoubtedly miss some, and thereby cause breaking changes in the future, or saddle the runtime with implementation-defined behaviour.

The costs would be enormous, so the benefit had better be enormous. I'm not seeing an enormous benefit here.


OK, if you didn't like my previous answer, then let's take a different tack.

Your question presupposes a falsehood: that we need a reason to not implement a feature. On the contrary, we need a very, very good reason to implement any feature. Features are enormously expensive in their up-front costs, in their maintenance costs, and in the opportunity costs. (That is, the time you spend on feature X is time you cannot spend on doing feature Y, and which might prevent you from ever doing feature Z.) In order to responsibly deliver value to our customers and stakeholders, we cannot implement every feature that someone happens to like.

It's not up to the runtime designers to justify why they did not implement a feature that you find particularly nice. Features are prioritized based on their costs vs the benefit to users, and users have not exactly been hammering down my door demanding this kind of inheritance. This particular feature would massively change how analysis of the type system works in the runtime, have far-reaching effects on every language that consumes generics, and seems to me to provide very little benefit.

We use this sort of inheritance in the compiler -- written in C++ -- and the resulting code is difficult to follow, hard to maintain, and confusing to debug. I've been doing my best to gradually eliminate code like this. I'm opposed to enabling the same sort of bad patterns in C# unless there is an enormously compelling benefit to doing so.

The task of describing that enormous benefit in a compelling way is laid upon the people who want the feature, not upon the people who would have to implement it. So what's the compelling benefit?


Example of code, where this could help:

public class SpecialDataRow<T> : T where T : DataRow
{
    public int SpecialFactor { get; set; }
}

This would enable making 'special' rows from DataRow and also from any derived DataRows (like typed dataset generated ones)

I do not see any other way how to code such a class


What would be so useful about this?

Remember that despite the name, generics were never intended to support generic programming.

To support a feature like this, they'd have to make some pretty dramatic changes to the CLR.

You'd need to define a class that derives from a type that doesn't even exist at compile-time.

Why should they jump through such hoops and pretty fundamentally compromise their type system just to add this feature? Is it worth it?

If you think so, tell them why. Write feedback on connect.microsoft.com telling them why this feature is so fundamental that it must be added.


C++ templates cannot be compared to C# generics. C++ templates are pre-processed like macros, while generics in .NET are handled by the runtime.

But there are other people who know a lot more about that than me...

0

精彩评论

暂无评论...
验证码 换一张
取 消