首页 > 解决方案 > C# 中的泛型类型约束

问题描述

我正在查看通用类型约束的 MSDN 文档,并找到了以下段落。

您使用默认约束来指定您的派生类覆盖没有派生类中的约束或显式接口实现的方法。它仅对覆盖基本方法或显式接口实现的方法有效:

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 { }
}

我无法理解派生类在没有约束的情况下覆盖该方法的部分。这可以用一个详细的例子来解释,在“M”方法中需要为 T 传递值吗?

标签: c#.net

解决方案


如果您尝试这样做,可能会更容易理解。假设您有:

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!"); 
    }
}

现在,您有一个子类,您要在其中覆盖唯一的虚拟方法:

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

一切都好,对吧?好吧,不完全是,不:

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>'

正如文档所解释的,编译器无法解决T?(可为空的引用类型)和T?(的简写Nullable<T>)之间的歧义,因此您需要一种方法来指定可以覆盖的方法。这就是新default约束变得有用的地方:

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

现在它实际上编译了。现场观看:https ://dotnetfiddle.net/vXgzWx


推荐阅读