简体   繁体   中英

Generic type constraint in C#

I was going through the MSDN document for the Generic type constraint and I found the following paragraph.

You use the default constraint to specify that your derived class overrides the method without the constraint in your derived class, or explicit interface implementation. It's only valid on methods that override base methods, or explicit interface implementations:

public class D : B
{
    // Without the "default" constraint, the compiler tries to override the first method in B
    public override void M<T>(T? item) where T : default { }
}

I couldnt understand the part of derived class overriding the method without the constraint. Can this please be explained with an elaborated example with the value needs to be passed for T in "M" method?

It might be easier to understand if you try to do it. Let's say you have:

public abstract class BaseLogger
{
    public void Log<T>(T? item) where T : struct 
    { 
        Console.WriteLine("I **cannot** be overriden!"); 
    }

    public virtual void Log<T>(T? item) 
    {
        Console.WriteLine("I **can** be overriden!"); 
    }
}

Now, you have a child class, where you want to override the only virtual method:

public class Logger : BaseLogger
{
    public override void Log<T>(T? item) 
    {
        Console.WriteLine("I am overwriting my parent method!"); 
    }
}

All good, right? Well, not exactly, no:

Compilation error: 'Logger.Log<T>(T?)': cannot override inherited member 'BaseLogger.Log<T>(T?)' because it is not marked virtual, abstract, or override
Compilation error: The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable<T>'

As the document explains, the compiler cannot resolve the ambiguity between T? (a nullable reference type) and T? (the shorthand for Nullable<T> ), so you need a way to specify the method that can be overriden. That's where the new default constraint becomes useful:

public class Logger : BaseLogger
{
    public override void Log<T>(T? item) where T: default
    {
        Console.WriteLine("I am overwriting my parent method!"); 
    }
}

Now it actually compiles. See it live: https://do.netfiddle.net/vXgzWx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM