这就是所谓的Curiously_recurring_template_pattern (CRTP),据我了解,这并不是严格要求的(实际上它不能强制执行“正确”的行为),但如.NET 6 \xe2\x80\ 中的预览功能中所述x93 Generic Math文章它的用法是支持静态抽象接口成员调用的非常重要的场景之一的提示 - 通过泛型接口使用它:
\n\n\n这种通用模式有时称为奇怪的重复模板模式 (CRTP),并且是允许该功能发挥作用的关键。
\n
让我们想象一下以下界面:
\npublic interface IParseable1<TSelf>\n // where TSelf : IParseable1<TSelf>\n{\n static abstract TSelf Parse(string s, IFormatProvider? provider);\n\n static abstract bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out TSelf result);\n}\nRun Code Online (Sandbox Code Playgroud)\n和下一个方法:
\nstatic T InvariantParse<T>(string s)\n where T : IParseable1<T>\n{\n return T.Parse(s, CultureInfo.InvariantCulture);\n}\nRun Code Online (Sandbox Code Playgroud)\n如果我们实现下一个类对:
\nclass MyClass1\n{\n}\n\nclass MyClass : IParseable1<MyClass1>\n{\n public static MyClass1 Parse(string s, IFormatProvider? provider)\n {\n throw new NotImplementedException();\n }\n\n public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out MyClass1 result)\n {\n throw new NotImplementedException();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n那么下一个调用将无法编译:
\nvar x = InvariantParse<MyClass>("");\nRun Code Online (Sandbox Code Playgroud)\n虽然 CRTP 不能防止“不正确”的使用(即class MyClass1 : IParsable<MyClass1>允许class MyClass : IParsable<MyClass1>,据我记得没有语言构造来强制执行这种行为),但它强烈暗示了所需的用法。
请注意,class MyClass : IParsable<MyClass1>可以在类似的方法中使用,但它变得相当笨拙(部分原因是 C# 泛型类型推断的细节):
public static TOut InvariantParseTwoGenerics<T, TOut>(string s)\n where T : IParseable1<TTO>\n{\n return T.Parse(s, CultureInfo.InvariantCulture);\n}\n\nvar x1 = InvariantParseTwoGenerics<MyClass, MyClass1>("");\nRun Code Online (Sandbox Code Playgroud)\nStephen Cleary 发表的讨论 CRTP 的帖子。
\nUPD
\n.NET 6 和 .NET 7 之间发生了重大变化System.IParseable-更名为System.IParsable