如何使用枚举安全地重载构造函数?C#

本文关键字:构造函数 重载 何使用 枚举 安全 | 更新日期: 2023-09-27 18:24:10

我有这个代码

public enum MyEnumOne : byte { ... }
public enum MyEnumTwo : byte { ... }
public class MyClass
{
    public readonly MyEnumOne E1;
    public readonly MyEnumTwo E2;
    private MyClass(MyEnumOne e1)
    {
        E1 = e1;
    }
    private MyClass(MyEnumTwo e2)
    {
        E2 = e2;
    }
    public static MyClass CreateWithE1(MyEnumOne e1)
    {
        return new MyClass(e1);
    }
    public static MyClass CreateWithE2(MyEnumTwo e2)
    {
        return new MyClass(e2);
    }
}

我如何才能确保这段代码总是会抛出正确的构造函数重载?

var A = MyClass.CreateWithE1(0);
var B = MyClass.CreateWithE2(0);

我可以通过使类可变来确保这一点,但我不需要类是可变的。

注意:如果我犯了任何错误,使类不可变,请告诉我:)

编辑:两个枚举的第一个元素都是None = 0,在合法的情况下,可以创建一个枚举为None的实例。

如何使用枚举安全地重载构造函数?C#

编译CreateWithE1时,它包含对基于MyEnumOne的构造函数的调用。

类似地,当CreateWithE2编译时,它包含对基于MyEnumTwo的构造函数的调用。

当这两个方法中的任何一个被调用时,要使用的构造函数已经固定到位,并且不是基于参数的运行时

当使用隐式转换调用任何重载方法时,由于int和enum之间存在,编译器会根据可转换类型推断出您想要的方法,就像直接调用方法一样。然而,如果它遇到歧义,那么,它将抛出那个错误——"歧义匹配"

因此,上面的构造函数是安全的,但会强制任何实现显式地指定要传入的类型,这样编译器就可以正确地推断。然而,由于您的方法采用特定的枚举,它们对编译器来说是可区分的,从而使上述代码顺利通过编译器。

如果你想避免工厂的方法,你可以做以下

var A = new MyClass((MyEnumOne)0);
var B = new MyClass((MyEnumTwo)0);

请务必阅读显式和隐式转换,以及编译器如何解决重载。

以最安全的方式实现的方法如下:

l_param.DbType=(DbType)Enum.Parse(typeof(DbType),param.dataType);

public readonly MyEnumOne E1;
public readonly MyEnumTwo E2;
private MyClass(MyEnumOne e1)
{
    E1 = (MyEnumTwo)Enum.Parse(typeof(MyEnumTwo), e1);
}

其他转换也是如此。