Question

Hé, je pense avoir ici une mauvaise idée, mais je ne suis pas sûr ce qui est mieux. Je veux une classe avec une variable membre qui peut être de tout type, en fonction de ce qui est nécessaire à l'époque. Jusqu'à présent, j'ai quelque chose comme ceci:

    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;
    }
}

Le type renvoyé par le côté droit de la ligne « this.value » est une chaîne, en ce moment. Je sais ici, il semble que je n'ai pas besoin d'utiliser autre chose que le type de chaîne, mais finalement je vais développer le constructeur, de sorte que « this.value » pourrait être une chaîne, int, float, ou bool.

Quoi qu'il en soit, mon compilateur dit « Impossible de convertir « string » « T » », donc je suppose que je fais quelque chose de très en arrière.

Merci.

Était-ce utile?

La solution

Eh bien, quelle conversion vous attendiez-vous à appliquer? Si vous attendez que la valeur soit déjà du bon type, vous pouvez faire:

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

Notez que vous devez passer par object implicitement (comme ici) ou avec un casting explicite:

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

L'ensemble des conversions prévues types génériques est quelque peu limitée. Mais il devrait fonctionner si la valeur d'origine est vraiment correcte.

Autres conseils

Vous êtes en cours d'exécution dans des problèmes parce que ce n'est pas une bonne utilisation des médicaments génériques. Si le paramètre de type générique ne peut être construit de quatre manières différentes - string, float, bool et int - alors ce n'est pas très générique . Je pense qu'une chose peut être générique tout type du tout .

Si j'avais une chose qui ne pouvait être l'un des quatre types alors je ce modèle comme ceci:

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

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

class BooleanSetting : ConfigSetting
{ /* ... 

et ainsi de suite. Je serais probablement alors donner à chacun d'eux un constructeur interne et faire la classe de base dans une usine pour les classes dérivées, en utilisant le modèle d'usine.

Utiliser uniquement des médicaments génériques si votre solution est vraiment générique . Comme List<T>, par exemple, peut être une liste de quoi que ce soit : ints, chaînes, des tableaux, des dictionnaires, des fonctions, peu importe. Si la chose que vous modélisez a un petit nombre de types possibles, juste faire un pour chaque type.

Vous devez lancer la chaîne retourné à T:

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

Je pense que vous ne devriez pas utiliser nécessairement génériques pour planifier à l'avance pour tous les scénarios futurs possibles parce que vous aurez probablement courir dans des cas de pointe dans l'avenir et doivent modifier le code indépendamment.

Toutefois, si vous avez déjà plusieurs scénarios qu'un générique cadrerait, alors vous pouvez bénéficier de la réutilisation logique maintenant et peut les tester correctement.

Je vois que d'autres ont déjà fourni des réponses de code, donc je vais arrêter ici.

Je suppose que

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

est une chaîne.

Vous ne pouvez pas assigner une chaîne à this.value car le type de this.value est T et pourrait être quelque chose, comme les types auxquels les chaînes ne sont pas cessibles.

Une solution consiste à supprimer le paramètre générique et faire value une chaîne, puis fournir différents moyens d'accéder à ce qui compilent bools, flotteurs, ou tout au besoin.

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

// etc

On dirait que vous essayez d'assigner une chaîne (configsettings.SettingGroups[heading].Settings[key].RawValue) sur l'élément générique. Vous devrez fournir un moyen de convertir la chaîne en type T - généralement par coulée. Par exemple:

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

Dans cette ligne:

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

vous définissez votre variable de type T à une valeur de chaîne. La méthode rawvalue retourne une chaîne. Vous devez jeter explicitement taper T.

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

est vraiment T ne va être que des valeurs sans constructeurs? Vous pourriez être en mesure de faire ce explicite et éviter les objet coulée, si vous voulez éviter que, pour une raison quelconque.

Essayez un

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

si vous avez vos valeurs de configuration stockées sous forme de chaînes et souhaitez converti en bon type. Cela ne fonctionne que pour la plupart des types primitifs comme Int32, Double, etc.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top