【问题标题】:ambiguous/conflicting constructors in generic class泛型类中的模棱两可/冲突的构造函数
【发布时间】:2009-10-09 20:39:13
【问题描述】:

我有一个通用类:

public class BaseFieldValue<T>
{
    public BaseFieldValue()
    {
        //...
    }

    public BaseFieldValue(string value)
    {
        //...
    }

    public BaseFieldValue(T value)
    {
        //...
    }
}

很好。除了...

var myValue = new BaseFieldValue<string>("hello");

哎呀。调用了不需要的构造函数。有很多方法可以解决这个问题。最好的解决方案是什么?

【问题讨论】:

  • 也许你可以试试这个:var myValue = new BaseFieldValue("hello" as Object);

标签: c# generics


【解决方案1】:

我可能会将其中一个重载变成工厂方法:

public static BaseFieldValue<T> Parse(string value){}

【讨论】:

  • 如果BaseFieldValue是数据库连接类,字符串是连接字符串怎么办?
  • @Yuriy 在这种情况下这仍然是可行的。
  • @Rex,是的,但它与其他数据库连接类不同,只是试图保留模式。
  • 我和我们的开发团队一起测试了这个实现,他们发现它非常直观。干杯!
【解决方案2】:

您可以执行以下操作:

public class BaseFieldValue<T>
{
    public struct Special
    {
        internal string m_value;
        public Special(string value)
        {
            m_value = value;
        }
    }

    public BaseFieldValue()
    {
        //...
    }

    public BaseFieldValue(Special value)
    {
        //...
    }

    public BaseFieldValue(T value)
    {
        //...
    }
}

...或者,您可以在特殊构造函数中添加一个额外忽略的布尔参数,以消除歧义。

【讨论】:

    【解决方案3】:

    无法让类型约束做我想做的事,所以我的解决方法是删除模棱两可的构造函数,同时保留字符串的特殊情况:

    public class BaseFieldValue<T>
    {
        public BaseFieldValue()
        {
            //...
        } 
    
        public BaseFieldValue(T value) 
        {
            //however many things you need to test for here
            if (typeof(T) == typeof(string))
            {
                SpecialBaseFieldValue(value.ToString());
            }
            else
            {
                //everything else
            }
            //...
        }
    
        private void SpecialBaseFieldValue(string value)
        {
            //...
        }
    
    }
    

    【讨论】:

    【解决方案4】:

    一个令人讨厌的 hack,但可能并不比任何替代方案差:

    public class BaseFieldValue<T>
    {
        public BaseFieldValue()
        {
            // ...
        }
    
        public BaseFieldValue(StringWrapper value)
        {
            // ...
        }
    
        public BaseFieldValue(T value)
        {
            // ...
        }
    
        public class StringWrapper
        {
            private string _value;
    
            public static implicit operator string(StringWrapper sw)
            {
                return sw._value;
            }
    
            public static implicit operator StringWrapper(string s)
            {
                return new StringWrapper { _value = s };
            }
        }
    }
    

    现在可以根据需要使用:

    // call the generic constructor
    var myValue = new BaseFieldValue<string>("hello");
    
    // call the string constructor
    var myValue = new BaseFieldValue<int>("hello");
    

    【讨论】:

      【解决方案5】:

      也许你可以试试:

      var myValue = new BaseFieldValue<Object>("hello" as Object);  
      

      【讨论】:

      • @Amy 这似乎违背了拥有泛型类的目的。
      猜你喜欢
      • 2020-05-11
      • 1970-01-01
      • 2014-10-21
      • 2010-10-16
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      • 1970-01-01
      • 2019-02-20
      相关资源
      最近更新 更多