调用具有从单个参数派生的两个参数的基本构造函数

时间:2019-02-21 19:54:15

标签: c# .net constructor initialization

我有一个在其构造函数中带有两个参数的基类:

public class BaseClass {
    public BaseClass(string key, object value) { ... }
}

我的派生类的构造不同,使用一个复杂的参数,然后我可以将其拆分为基类参数。

public class DerivedClass : BaseClass {
    public DerivedClass (string keyValuePair)
        : BaseClass( SomethingExpensive(keyValuePair).Key,
                     SomethingExpensive(keyValuePair).Value) { }

    private static KeyValuePair<string,object> SomethingExpensive(string input) { 
         // Do expensive things
         return new KeyValuePair<string,object>(derivedKey, derivedValue);
    }    
}

鉴于我无法控制BaseClass并且不能给它一个新的构造函数,我试图找到一种无需两次调用SomethingExpensive就可以传递这些参数的方式。


我考虑过在第一次调用期间使用out参数为其他构造函数参数生成新的标识符:

public class DerivedClass : BaseClass {
    public DerivedClass (string keyValuePair)
        : BaseClass( SomethingExpensive(keyValuePair, out object _value), _value) { }

    private static string SomethingExpensive(string input, out object value) { 
         // Do expensive things
         value = derivedValue;
         return derivedKey;
    }    
}

但这在当前框架中被拒绝,并显示以下错误:

  

错误CS8107功能“成员初始化程序和查询中的表达式变量声明”在C#7.0中不可用。请使用语言版本7.3或更高版本。

还有其他选择吗?

3 个答案:

答案 0 :(得分:1)

我可以想到2种单独的方法,尽管不是彻底的解决方案:

  1. 您可以缓存键值对的解析结果,以使第二次调用不昂贵
  2. 您可以使用has-a而不是is-a关系模型。因此,基类不是派生的,而是一个包含的对象,由同一接口包装和公开。

希望这会有所帮助。

答案 1 :(得分:1)

只需在BaseClassDerivedClass之间添加适配器类

public class BaseClass {
    public BaseClass(string key, object value) { ... }
}

public class AdapterClass : BaseClass {
    public AdapterClass (SomethingExpensive se) : BaseClass(se.key, se.value) { ... }
}

public class DerivedClass : AdapterClass{
    public DerivedClass (string keyValuePair) : AdapterClass(SomethingExpensive(keyValuePair)) { }

    private static KeyValuePair<string,object> SomethingExpensive(string input) { 
        // Do expensive things
        return new KeyValuePair<string,object>(derivedKey, derivedValue);
    }    
}

答案 2 :(得分:1)

受@alex解决方案的启发,但不需要其他类:

public class DerivedClass : BaseClass {
    public DerivedClass (string keyValuePair)
        : this(SomethingExpensive(keyValuePair)) { }

    private DerivedClass (Tuple<string,object> arguments)
        : BaseClass(arguments.Item1, arguments.Item2)

    private static Tuple<string,object> SomethingExpensive(string input) { 
         // Do expensive things
         return Tuple.Create(derivedKey, derivedValue);
    }    
}