[英]Initialize a non-generic object with a generic object
Sometimes I do not get those T
s of C# Generics right. 有时候,我不明白那些T
的C#泛型正确s。 I have a generic struct 我有一个通用的结构
public struct ValueWithUnit<T>
{
public ValueWithUnit(T _value, Unit _unit)
{
Unit = _unit;
Value = _value;
}
public Unit Unit { get; }
public T Value { get; }
}
( Unit
is an enum
, T
should be numeric, but there is no constraint available for that purpose). ( Unit
是enum
, T
应该是数字,但没有可用于此目的的约束)。
For WCF I need a non-generic version of that, with T
being double
. 对于WCF,我需要一个非泛型版本, T
为double
。 So I thought of: 所以我想到了:
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; }
}
But the second constructor does not compile: error CS0246: The type or namespace name 'T' could not be found ...
and Convert.ToDouble complains with Cannot resolve method 'ToDouble(T)' Candidates are...
但是第二个构造函数没有编译: error CS0246: The type or namespace name 'T' could not be found ...
而Convert.ToDouble抱怨Cannot resolve method 'ToDouble(T)' Candidates are...
I know I can add a conversion method to the generic class: 我知道我可以在泛型类中添加转换方法:
public DoubleValueWithUnit ToDoubleValueWithUnit()
{
return new DoubleValueWithUnit(Convert.ToDouble(Value), Unit);
}
That works. 这样可行。 But is there any possibility to add a constructor with a generic parameter to a non-generic class/struct? 但是有没有可能将带有泛型参数的构造函数添加到非泛型类/结构中?
I don't think this constructor should exist at all: 我不认为这个构造函数应该存在:
public DoubleValueWithUnit(ValueWithUnit<T> _valueWithUnit)
{
Unit = _valueWithUnit.Unit;
Value = Convert.ToDouble(_valueWithUnit.Value);
}
Why do you want to convert a ValueWithUnit<T>
to a DoubleValueWithUnit
? 为什么要将ValueWithUnit<T>
转换为DoubleValueWithUnit
? With some values of T
, this does not make sense. 对于某些T
值,这没有意义。 How do you convert a BinaryFormatter
to double
? 你如何将BinaryFormatter
转换为double
? Or a Form
to double
? 还是要double
的Form
? These simply should not be allowed at compile time. 在编译时不应该允许这些。
So you either do this: 所以你要么这样做:
public DoubleValueWithUnit(ValueWithUnit<double> _valueWithUnit)
{
Unit = _valueWithUnit.Unit;
Value = _valueWithUnit.Value;
}
Or remove the constructor all together. 或者一起删除构造函数。
In the second example, T is simply not defined. 在第二个例子中,简单地没有定义T. So you cannot use T in the context of that struct. 所以你不能在该结构的上下文中使用T.
Just remove this constructor: 只需删除此构造函数:
public DoubleValueWithUnit(ValueWithUnit<T> _valueWithUnit)
Since you would like to convert anything passed to Double, define a constructor taking as input an object. 由于您希望转换传递给Double的任何内容,因此定义一个构造函数作为对象的输入。 In the constructor try to cast and throw an exception if the object is not convertible. 在构造函数中,如果对象不可转换,请尝试强制转换并抛出异常。
public DoubleValueWithUnit(object obj, Unit unit)
{
Unit = unit;
try
{
Value = Convert.ToDouble( obj );
}
catch( Exception )
{
throw new ArgumentException("Cannot convert to double", nameof(obj) );
}
}
My current solution is to have the struct implementing a generic interface which in turn inherits from a non-generic interface: 我目前的解决方案是让结构实现一个通用接口,该接口继承自非通用接口:
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; }
}
Now, I can pass a ValueWithUnit<T>
into the (modified) constructor: 现在,我可以将ValueWithUnit<T>
传递给(已修改的)构造函数:
public DoubleValueWithUnit(IValueWithUnit _valueWithUnit)
{
Unit = _valueWithUnit.Unit;
Value = Convert.ToDouble(_valueWithUnit.Value);
}
Still I am not sure if there are better solutions possible. 我仍然不确定是否有更好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.