【问题标题】:Constructor with string parameter and identical overload with object parameter带有字符串参数的构造函数和带有对象参数的相同重载
【发布时间】:2026-01-20 08:00:01
【问题描述】:

我的类目前有两个构造函数,都是重载:

public CustomRangeValidationAttribute(string value) {}

public CustomRangeValidationAttribute(object value) {}

这似乎工作正常:当我使用string 调用该方法时,调用了第一个构造函数,当我使用不同的值(例如integerboolean)时,调用了第二个构造函数。

我假设有一个规则强制特定类型匹配到更具体的重载中,防止

var c = new CustomRangeValidationAttrubute("test");

来自调用对象重载。

这是“安全代码”,还是应该(或可以)改进代码?我有一种唠叨的感觉,这不是最佳做法。

【问题讨论】:

  • 取决于,你想达到什么目标?
  • 我需要确保绝对没有调用错误构造函数的风险。如果不是这样的话,在某种程度上它仍然是一种不好的做法。
  • 如果基于object 的方法会做一些根本不同/错误如果它碰巧用string 调用,那可能是一个逻辑错误 首先创建重载,但与调用代码无关。
  • 请记住,重载将在编译时选择,因此如果您有一个实际上是字符串的对象引用,则将调用第二个重载(除非您将对象转换为字符串) .
  • @mjwills - 很难使用构造函数,因为在链接之前无法运行逻辑(在 C# 中)

标签: c# overloading constructor-overloading


【解决方案1】:

您有两个仅在引用类型上有所不同的重载,并且引用类型之间存在层次关系,因此可以将一个重载转换为另一个。

在这种情况下,您真的应该确保代码在选择更广泛的过载时表现相同的逻辑上 em>,但引用变出为更派生的类型 1 ,2是你要集中注意力的地方。当然,如果你能坚持这条规则,通常情况下,更多派生的重载不是必需的,可以在更广泛的方法中进行特殊情况。


1特别是因为,正如 vc74 在评论中指出的那样,重载解析(通常忽略 dynamic)是在编译时根据编译时类型完成的3.

2这符合同样广泛的重载原则。不要在选择哪个导致逻辑上不同的结果的情况下出现重载。如果您表现出不同的行为,请不要给它们取相同的名称(对于构造函数,这可能意味着拆分为两个单独的类,如果您打算这样做,则可能使用共享的基类)

3我很欣赏这是一个属性,所以你期望只有编译时间是相关的,但我仍然会在可能的情况下遵守一般原则。

【讨论】:

    【解决方案2】:

    一旦出现具有更多派生类型签名的重载,编译器将始终选择您提供的最具体的类型。

    话虽如此,除非有人这样​​做new CustomRangeValidationAttrubute((object)"test"),如果你将字符串传递给CustomRangeValidationAttrubute,总是会选择参数中带有string的构造函数。

    关于这是否是不好的做法,我无法确定是否看不到您的具体用例,请记住您传递给 new CustomRangeValidationAttrubute(object) 的每个值类型都将被装箱,这很糟糕给 GC 施加压力,而且你会失去类型安全性。

    【讨论】:

      【解决方案3】:

      我解决此代码的方法是将重载移动到具有单独方法的新抽象类,而不是原来的构造函数:

      public CustomRangeValidationStringAttribute(string value) {}
      
      public CustomRangeValidationGenericAttribute(object value) {}
      

      在从这个新基类继承的两个类中,每个类都使用自己的方法,创建两个不同的属性可供选择,[CustomRangeValidationString] 和 [CustomRangeValidationGeneric]。

      【讨论】:

        【解决方案4】:

        您可以使用泛型类。

        See the documentation

        class YourClass<T> 
        {
            public YourClass(T value){}
        }
        

        【讨论】:

        • 以为我没有明确说明,我的类是一个属性,继承自 RemoteAttribute 不幸的是,属性类中不允许使用泛型。
        最近更新 更多