c# – 如何从基类中实例化派生类

我已经扩展了这篇文章中给出的单位转换器类:
https://stackoverflow.com/a/7852721/1474894
这就是我现在拥有的:

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,TValueType>>();

    private static ConcurrentDictionary<TUnitType,TValueType>> ConversionsFrom = new ConcurrentDictionary<TUnitType,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,TValueType> conversionTo,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);
    }
}

我有这样的具体实现:

public enum TemperatureUnit
{
    [System.ComponentModel.Description("°C")]
    Celcius,[System.ComponentModel.Description("°F")]
    Fahrenheit
}

public class Temperature : UnitBase<TemperatureUnit,double>
{
    static Temperature()
    {
        BaseUnit = TemperatureUnit.Celcius;
        RegisterConversion(TemperatureUnit.Fahrenheit,x => x * 1.8d + 32d,x => (x - 32d) / 1.8d);
    }

    private Temperature(double value)
    {
        BaseValue = value;
    }

    public static Temperature Fromunit(double value,TemperatureUnit unit)
    {
        return new Temperature(Convert(value,unit,BaseUnit));
    }
}

我设法将ToUnit方法作为基类的一部分进行通用,但是使用Fromunit方法,我现在每个具体类都有一个(并且它们看起来都非常相似).我希望能够这样做:

Temperature temperature = Temperature.Fromunit(10,TemperatureUnit.Celcius);
Pressure pressure = Pressure.Fromunit(50,PressureUnit.Bar);

…无需在每个具体类中实现Fromunit.因为它是一个静态方法,所以我不能通过使用接口来强制执行.我可以在具体类中有一个公共构造函数,并具有以下内容

public static T Fromunit<T>(TValueType value,TUnitType unit) where T : new()
{
    BaseValue = Convert(value,BaseUnit);
    return new T();
}

但我想这不是那么好,我将不得不去:

Temperature temperature = Temperature.Fromunit<Temperature>(10,TemperatureUnit.Celcius);

<温度>我觉得有点多余.

是否有可能以更好的方式实现通用的Fromunit

编辑:
基本上我想要的是,而不是在每个子类中实现Fromunit

public static Temperature Fromunit(double value,TemperatureUnit unit)
{
    return new Temperature(Convert(value,BaseUnit));
}

public static Pressure Fromunit(double value,PressureUnit unit)
{
    return new Pressure(Convert(value,BaseUnit));
}

public static Speed Fromunit(double value,SpeedUnit unit)
{
    return new Speed(Convert(value,BaseUnit));
}

...

…将通用Fromunit放在基类中.

解决方法

<温度> “不太好”的解决方案中的类型参数可能看似多余,但实际上并非如此.当你写作

Temperature temperature = Temperature.Fromunit<Temperature>(10,TemperatureUnit.Celcius);

代码实际上已翻译成

Temperature temperature = UnitBase<TemperatureUnit,double>.Fromunit<Temperature>(10,TemperatureUnit.Celcius);

编译器非常好,允许您使用Temperature访问该方法.因为它实际上调用了UnitBase.Fromunit(),所以它不知道你真的想要使用Temperature,这就是为什么你必须提供它作为一个额外的类型参数.

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...