Вызов базового конструктора с двумя аргументами, полученными из одного аргумента - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть базовый класс, который принимает два аргумента в своем конструкторе:

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 голосов
/ 21 февраля 2019

Просто добавьте класс адаптера между BaseClass и DerivedClass

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);
    }    
}
0 голосов
/ 21 февраля 2019

Вдохновлено решением @ 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);
    }    
}
0 голосов
/ 21 февраля 2019

Я могу подумать о 2 разных подходах, хотя и не о прямых решениях:

  1. Вы можете кэшировать результат парсинга пары ключ-значение, чтобы второй вызов был не дорогим
  2. Вы можете использовать модель отношений «есть, а не есть».Так что базовый класс не является производным, а содержит объект, обернутый и предоставленный тем же интерфейсом.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...