Вопрос

Эй, я думаю, что у меня здесь неправильная идея, но я не уверен, что лучше. Я хочу класс с переменной -членом, которая может быть любого типа, в зависимости от того, что необходимо в то время. Пока что у меня есть что -то вроде этого:

    public class ConfigSetting<T> {
    private T value;

    public T GetValue() {
        return value;
    }
    public void ChangeValue() {

    }

    public ConfigSetting(string heading, string key) {
        this.value = DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;
    }
}

Тип, возвращаемый правой стороной линии 'this.value', в настоящее время является строкой. Я знаю, что мне кажется, что мне не нужно использовать что -либо, кроме типа строки, но в конце концов я расширирую конструктор, так что «это.

В любом случае, мой компилятор говорит «не может преобразовать« строку »в« t »», поэтому я предполагаю, что делаю что -то очень назад.

Спасибо.

Это было полезно?

Решение

Ну, какое преобразование вы ожидали от него применить? Если вы ожидаете, что значение уже будет правильного типа, вы можете сделать:

object tmp = DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;
this.value = (T) tmp;

Обратите внимание, что вам нужно пройти через object либо неявно (как здесь), либо с явным составом:

this.value = (T)(object) DerivedMethods.configsettings... (etc);

Набор конверсий, предоставленных для общих типов, несколько ограничен. Но это должно работать, если исходное значение действительно верно.

Другие советы

Вы сталкиваетесь с проблемами, потому что это не очень хорошее использование дженериков. Если параметр общего типа может быть построен только четырьмя различными способами - String, Float, Bool и Int - тогда это не очень общий. Анкет Я ожидаю, что общая вещь может быть любой тип вообще.

Если бы у меня была вещь, которая могла бы быть только одним из четырех типов, я бы моделировал это так:

abstract class ConfigSetting
{ /* shared code here */  }

class TextSetting : ConfigSetting
{ /* Code here to handle string settings */ }

class BooleanSetting : ConfigSetting
{ /* ... 

и так далее. Я бы, наверное, тогда дал бы каждому из них внутренний конструктор и превратил бы базовый класс в фабрика Для полученных классов, используя заводской шаблон.

Используйте дженерики, только если ваше решение действительно общий. Анкет Нравиться List<T>, например, может быть список что-либо: ints, струны, массивы, словари, функции, что угодно. Если то, что вы моделируете, имеет небольшое количество возможных типов, просто сделайте один для каждого типа.

Вам нужно бросить возвращенную строку в T:

public ConfigSetting(string heading, string key) {
    this.value = (T)DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;
}

Я думаю, что вы не обязательно должны использовать дженерики для планирования заранее для всех возможных будущих сценариев, потому что вы, вероятно, столкнетесь с случаями Edge в будущем и независимо от того, чтобы изменить код.

Однако, если у вас уже есть несколько сценариев, к которым подходит универсальный, то вы можете получить выгоду от повторного использования логики и сможете проверить их все правильно.

Я вижу, что другие уже предоставили кодовые ответы, поэтому я остановлюсь здесь.

Я предполагаю, что

DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue

это строка.

Вы не можете назначить строку this.value Потому что тип this.value является T и может быть что угодно, например, типы, на которые строки не назначаются.

Одним из решений является удаление общего параметра и сделать value Строка, а затем предоставляет различные способы получить доступ к ней, которые разрабатывают Bools, Flow или что -то еще по мере необходимости.

public float GetFloatValue {
    get { return float.Parse(this.value); }
}

// etc

Похоже, вы пытаетесь назначить строку (configsettings.SettingGroups[heading].Settings[key].RawValue) для общего члена. Вам нужно будет предоставить какой -то способ преобразования строки в тип T - обычно через кастинг. Например:

this.value = (T)DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;

В этой линии:

this.value = DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;

Вы устанавливаете свою переменную типа T на строковое значение. Метод RawValue возвращает строку. Вам нужно явно поднять его на тип T.

this.value = (T) (object) DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;

На самом деле T будут только значениями без конструкторов? Вы можете сделать это явным и избежать объект Кастинг, если вы хотите избежать этого по какой -то причине.

Попробуйте а

string strValue = DerivedMethods.configsettings.SettingGroups[heading].Settings[key].RawValue;
this.value = (T)Convert.ChangeType(strValue, typeof(T), CultureInfo.InvariantCulture)

Если у вас есть значения конфигурации, хранящиеся как строки, и вы хотите преобразовать в правильный тип. Это работает только для большинства примитивных типов, таких как Int32, Double и т. Д.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top