C# 如何从基类通用地实例化派生类
我扩展了本文中给出的单位转换器类: 这就是我现在拥有的:C# 如何从基类通用地实例化派生类,c#,class,oop,design-patterns,generics,C#,Class,Oop,Design Patterns,Generics,我扩展了本文中给出的单位转换器类: 这就是我现在拥有的: public abstract class UnitBase<TUnitType, TValueType> where TUnitType : struct, IComparable, IConvertible, IFormattable { protected static TUnitType BaseUnit; protected static TValueType BaseValue; priv
public abstract class UnitBase<TUnitType, TValueType> where TUnitType : struct, IComparable, IConvertible, IFormattable
{
protected static TUnitType BaseUnit;
protected static TValueType BaseValue;
private static ConcurrentDictionary<TUnitType, Func<TValueType, TValueType>> ConversionsTo = new ConcurrentDictionary<TUnitType, Func<TValueType, TValueType>>();
private static ConcurrentDictionary<TUnitType, Func<TValueType, TValueType>> ConversionsFrom = new ConcurrentDictionary<TUnitType, Func<TValueType, TValueType>>();
public static TValueType Convert(TValueType value, TUnitType from, TUnitType to)
{
// If both From/To are the same, don't do any work.
if (from.Equals(to))
return value;
// Convert into the base unit, if required.
var valueInBaseUnit = from.Equals(BaseUnit)
? value
: ConversionsFrom[from](value);
// Convert from the base unit into the requested unit, if required
var valueInRequiredUnit = to.Equals(BaseUnit)
? valueInBaseUnit
: ConversionsTo[to](valueInBaseUnit);
return valueInRequiredUnit;
}
protected static void RegisterConversion(TUnitType convertToUnit, Func<TValueType, TValueType> conversionTo, Func<TValueType, TValueType> conversionFrom)
{
if (!ConversionsTo.TryAdd(convertToUnit, conversionTo))
throw new ArgumentException("Already exists", "convertToUnit");
if (!ConversionsFrom.TryAdd(convertToUnit, conversionFrom))
throw new ArgumentException("Already exists", "convertToUnit");
}
public static string GetUnit(TUnitType unit)
{
var type = typeof(TUnitType);
if (!type.IsEnum)
{
throw new ArgumentException();
}
return Enums.GetEnumDescription(unit as Enum);
}
public TValueType InUnit(TUnitType unit)
{
return Convert(BaseValue, BaseUnit, unit);
}
}
…而不必在每个具体类中实现FromUnit。因为它是一个静态方法,所以我不能使用接口强制实现。我可以在具体类中有一个公共构造函数,并有如下内容:
public static T FromUnit<T>(TValueType value, TUnitType unit) where T : new()
{
BaseValue = Convert(value, unit, BaseUnit);
return new T();
}
…将泛型FromUnit放入基类。为什么不将FromUnit实现推送到UnitBase本身:
public static TValueType FromUnit(TValueType value, TUnitType unit)
{
return Convert(value, BaseUnit, unit);
}
“not so nice”解决方案中的
类型参数可能看起来是多余的,但实际上并非如此。当你写作时
Temperature temperature = Temperature.FromUnit<Temperature>(10, TemperatureUnit.Celcius);
Temperature-Temperature=Temperature.from单位(10,TemperatureUnit.Celcius);
代码实际上被翻译为
Temperature temperature = UnitBase<TemperatureUnit, double>.FromUnit<Temperature>(10, TemperatureUnit.Celcius);
Temperature-Temperature=UnitBase.FromUnit(10,TemperatureUnit.Celcius);
编译器非常好,允许您使用
Temperature
访问该方法。因为它实际上调用的是UnitBase.FromUnit()
,所以它不知道您实际上想要使用Temperature
,这就是为什么您必须提供它作为一个附加类型参数的原因。这正是我想要做的,但是对于FromUnit,我想要返回具体类的实例(例如Temperature),而不是TValueType(例如双倍)。您的问题中不应该有xml注释,仅供参考。这会使您的问题变得过长。好的,我删除了xml注释。感谢您的提示。好的,额外的
类型参数可能没那么糟糕,但我可能会坚持在每个子类中使用FromUnit实现,这样我就可以执行温度=tTemperature.FromUnit(10,TemperatureUnit.Celcius);
我将能够保持每个子类的构造函数私有。无论如何,谢谢!
public static Temperature FromUnit(double value, TemperatureUnit unit)
{
return new Temperature(Convert(value, unit, BaseUnit));
}
public static Pressure FromUnit(double value, PressureUnit unit)
{
return new Pressure(Convert(value, unit, BaseUnit));
}
public static Speed FromUnit(double value, SpeedUnit unit)
{
return new Speed(Convert(value, unit, BaseUnit));
}
...
public static TValueType FromUnit(TValueType value, TUnitType unit)
{
return Convert(value, BaseUnit, unit);
}
Temperature temperature = Temperature.FromUnit<Temperature>(10, TemperatureUnit.Celcius);
Temperature temperature = UnitBase<TemperatureUnit, double>.FromUnit<Temperature>(10, TemperatureUnit.Celcius);