2017-05-30 90 views
3

有时候,我真不明白那些T C#的泛型的权利。我有一个通用的结构初始化非通用对象与通用对象

public struct ValueWithUnit<T> 
{ 
    public ValueWithUnit(T _value, Unit _unit) 
    { 
     Unit = _unit; 
     Value = _value; 
    } 
    public Unit Unit { get; } 
    public T Value { get; } 
} 

UnitenumT应该是数字,但没有可用于该目的的约束)。

对于WCF我需要一个非通用版本的,Tdouble。于是我想到了:

public struct DoubleValueWithUnit 
{ 
    public DoubleValueWithUnit(double _value, Unit _unit) 
    { 
     Unit = _unit; 
     Value = _value; 
    } 
    public DoubleValueWithUnit(ValueWithUnit<T> _valueWithUnit) 
    { 
     Unit = _valueWithUnit.Unit; 
     Value = Convert.ToDouble(_valueWithUnit.Value); 
    } 
    public Unit Unit { get; set; } 
    public double Value { get; set; } 
} 

但第二个构造不会编译: error CS0246: The type or namespace name 'T' could not be found ...和Convert.ToDouble与 Cannot resolve method 'ToDouble(T)' Candidates are...

抱怨我知道我可以添加一个转换方法泛型类:

public DoubleValueWithUnit ToDoubleValueWithUnit() 
    { 
     return new DoubleValueWithUnit(Convert.ToDouble(Value), Unit); 
    } 

工程。但有没有可能添加一个具有泛型参数的构造函数到非泛型类/结构?

+4

你为什么不只是使用'ValueWithUnit '而不是DoubleValueWithUnit'的'? – Maarten

+0

你试图做什么[是不可能的(https://开头计算器。com/questions/700966/generic-type-in​​-constructor) - 但是,Maarten的建议可能是这里最好的解决方案 – Rob

+0

@Maarten,因为WCF与​​泛型兼容...... –

回答

0

在第二个例子中,T是根本无法限定。所以你不能在该结构的上下文中使用T.

只是删除此构造函数:

public DoubleValueWithUnit(ValueWithUnit<T> _valueWithUnit) 

既然你想什么传递给双转换,定义构造函数作为输入的对象。在构造函数中,如果对象不可转换,则尝试转换并抛出异常。

public DoubleValueWithUnit(object obj, Unit unit) 
{ 
    Unit = unit; 
    try 
    { 
     Value = Convert.ToDouble(obj); 
    } 
    catch(Exception) 
    { 
     throw new ArgumentException("Cannot convert to double", nameof(obj)); 
    }   
} 
+0

在构造函数中抛出异常也不是一个好主意。只是通知。 – kuskmen

+0

@kuskmen合同正是这样工作的。别介意。 (你说的不是真的) – sam

2

我不认为这个构造函数应该存在:

public DoubleValueWithUnit(ValueWithUnit<T> _valueWithUnit) 
{ 
    Unit = _valueWithUnit.Unit; 
    Value = Convert.ToDouble(_valueWithUnit.Value); 
} 

你为什么要到ValueWithUnit<T>转换为DoubleValueWithUnit?有些值为T,这是没有意义的。你如何将BinaryFormatter转换为double?或者一个Formdouble?这些在编译时不应该被允许。

所以,你做这一点:

public DoubleValueWithUnit(ValueWithUnit<double> _valueWithUnit) 
{ 
    Unit = _valueWithUnit.Unit; 
    Value = _valueWithUnit.Value; 
} 

或删除构造都在一起。

+0

“你为什么要转换” - WCF不适应泛型。 “T”是事实上的数字,但是没有“where T:numeric”可用。 –

+0

@BernhardHiller我明白了。然后我建议你为每个数字类型编写一个构造函数。 – Sweeper

0

我的当前的解决方案是为具有实现的通用接口,其依次从一个非通用接口继承的结构:

public struct ValueWithUnit<T> : IValueWithUnit<T> {...} 

public interface IValueWithUnit<out T> : IValueWithUnit // where T: number 
{ 
    new T Value { get; } 
} 
public interface IValueWithUnit 
{ 
    object Value { get; } 
    Unit Unit { get; } 
} 

现在,我可以传递一个ValueWithUnit<T>进入(经修饰)构造:

public DoubleValueWithUnit(IValueWithUnit _valueWithUnit) 
{ 
    Unit = _valueWithUnit.Unit; 
    Value = Convert.ToDouble(_valueWithUnit.Value); 
} 

不过我不知道是否有可能更好的解决方案。