基类中返回派生类型的C#方法

3

我正在尝试在基类中创建一个方法,该方法能够返回派生类型。它不必实际驻留在基类中,但我不想在所有派生类中实现该方法。

像这样。

public class Error
{
    protected Error() { }

    public string Message { get; protected set; }

    public static Error Because(string msg)
    {
        return new Error() { Message = msg };
    }
}

然后我创建了两个派生类型:

public class MyError : Error
public class OtherError : Error

我可以使用Because实例化对象,而不需要进一步的实现。

我知道我可以像这样进行实现:

public static T Because<T>(string message)
    where T : Error
{
    var error = default(T);
    error.Message = message;

    return error;
}

但是我必须指定类型参数:
MyError err = Error.Because<MyError>("My error");

或者

MyError simp = MyError.Because<MyError>("My error");

我希望能够像这样调用它:

MyError myError = MyError.Because("Something went wrong");
OtherError myError = OtherError.Because("Something else went wrong");

1
静态方法不会被继承,因此如果您希望在派生类中定义它们,则必须在那里实现它们。为什么不使用构造函数来实现呢? - juharr
@juharr 我绝对可以在Error中定义我的静态泛型方法Because<T>,并使用OtherError.Because<OtherError>("My error")调用它,即使我只在Error中实现了它。 - dropbear
你的派生类中没有添加任何新成员吗?否则,您需要一些机制从基类内部填充这些属性。 - MakePeaceGreatAgain
@HimBromBeere 目前我只是在尝试一些东西。但现在不是这种情况。我希望派生类能够根据发生的错误返回和处理不同的错误。 - dropbear
工厂模式怎么样?当然,它不会让你使用上面写的完全相同的语法,但是类似于 Error.Because<MyError>("Something went wrong") 这样的语法。既然你在编译时已经知道类型了,我看不出你提到的语法有什么优势。实际上,OtherError.Because 解析成的就是这个样子,因为静态成员不会被继承。 - MakePeaceGreatAgain
2个回答

4

看起来这里适合使用奇异递归模板模式

例如:

    public abstract class Error<ConcreteError>
        where ConcreteError : Error<ConcreteError>, new()
    {
        protected Error() { }

        public string Message { get; protected set; }

        public static ConcreteError Because(string msg)
        {
            return new ConcreteError() { Message = msg };
        }
    }
    public class MyError : Error<MyError> { }
    public class OtherError : Error<OtherError> { }

    static void Main(string[] args)
    {

        MyError myError = MyError.Because("Something went wrong");
        OtherError myError2 = OtherError.Because("Something else went wrong");
    }

很高兴它有帮助。 - Renat

1
您描述的功能是返回类型协变,这是一项被接受和支持的语言特性,将在C#语言的下一个版本中实现。目前发布计划为C# 9.0。
有关更多详细信息,请查看相应的dotnet/csharplang讨论主题: 支持“协变返回类型”的倡导者

听起来将来做这件事会更容易。感谢您的贡献。 :) - dropbear

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接