【问题标题】:How can I safely overload a constructor with enums? C#如何安全地使用枚举重载构造函数? C#
【发布时间】:2014-09-24 14:37:36
【问题描述】:

我有这个代码

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 的实例。

【问题讨论】:

  • 我认为它足够安全。由于您使用 MyEnumOneMyEnumTwo 作为参数类型。您是否收到任何关于模糊呼叫的警告?
  • 或者您是否担心使用仅存在于E2 中的 调用CreateWithE1
  • 怎么可能使用正确的构造函数重载?如果你传入一个类型为MyEnumOne 的对象,它怎么可能调用MyEnumTwo 重载?如果您尝试显式调用该重载(通过删除另一个),它甚至不会编译。
  • @TimSchmelter 这些方法有不同的名称,所以一开始就没有删除的风险。如果他试图重载一个方法/构造函数,他会得到一个编译时歧义错误,你只是用运行时错误来掩盖它。
  • 爱失败的工厂 - 还要添加一个 [Obsolete("Don't call with an int", true)] 以导致编译器失败。

标签: c# constructor enums overloading


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    当使用implicit 转换调用任何重载方法时,就像在 int 和 enum 之间一样,编译器会根据可转换类型推断出您想要的方法,就像直接调用方法一样。但是,如果它遇到歧义,那么它只会抛出那个错误 - “歧义匹配”。

    因此,上述构造函数将是安全的,但会强制任何实现显式指定它们想要传入的类型,以便编译器可以正确推断。但是,由于您的方法采用特定的枚举,因此 它们 对编译器来说是可区分的,因此上述代码可以毫无问题地通过编译器。

    如果您想避免使用工厂方法,可以执行以下操作

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

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

    【讨论】:

      【解决方案3】:

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

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

      其他转换也是如此。

      【讨论】:

      • 对不起,如果有人弄错了。我不想从 E1 解析到 E2 或反之亦然。我想要的是调用正确的构造函数,无论调用函数的人是否在没有足够明确的情况下使用该函数,但无论如何都要感谢;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多