Domanda

Ehi, penso di avere un'idea sbagliata qui, ma non sono sicuro di quello che è il migliore. Voglio una classe con una variabile membro che può essere di qualsiasi tipo, a seconda di ciò che è necessario al momento. Finora, ho qualcosa di simile a questo:

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

Il tipo restituito dal lato destro della linea 'this.value' è una stringa, attualmente. So che qui sembra che non ho bisogno di usare qualcosa di diverso dal tipo di stringa, ma alla fine io ampliare il costruttore, in modo tale che 'this.value' potrebbe essere una stringa, int, float, o bool.

In ogni caso, il mio compilatore dice "Impossibile convertire 'stringa' a 'T'", quindi suppongo che sto facendo qualcosa di molto all'indietro.

Grazie.

È stato utile?

Soluzione

Beh, che la conversione ti aspettavi di applicare? Se si prevede che il valore sia già del tipo giusto, si potrebbe fare:

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

Si noti che si deve passare attraverso object in modo implicito (come qui) oppure con un cast esplicito:

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

L'insieme di conversioni previste tipi generici è alquanto limitata. Ma dovrebbe funzionare se il valore originale è davvero corretto.

Altri suggerimenti

si sta eseguendo in problemi perché questo non è un buon uso dei farmaci generici. Se il parametro di tipo generico può essere costruito solo in quattro modi diversi - string, float, bool e int - allora questo non è molto generici . Mi aspetto che una cosa generica può essere qualsiasi tipo a tutti .

Se avessi una cosa che potrebbe essere solo uno dei quattro tipi quindi vorrei modellare in questo modo:

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

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

class BooleanSetting : ConfigSetting
{ /* ... 

e così via. Io probabilmente allora dare a ciascuno di loro un costruttore interna, e rendere la classe base in una fabbrica di per le classi derivate, utilizzando il modello di fabbrica.

Utilizzare solo farmaci generici se la soluzione è davvero generici . Come List<T>, per esempio, può essere un elenco di niente : ints, stringhe, array, dizionari, funzioni, a prescindere. Se la cosa si sta modellando ha un piccolo numero di possibili tipi, basta fare uno per ogni tipo.

È necessario lanciare la stringa restituita al T:

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

Credo che non si deve necessariamente utilizzare farmaci generici di pianificare in anticipo per tutti i possibili scenari futuri, perché è probabile imbattersi in casi limite in futuro e deve modificare il codice a prescindere.

Tuttavia, se si dispone già di scenari multipli che un generico si adatterebbe a, allora si può beneficiare del riutilizzo logica ora e li può testare in modo corretto.

Vedo che altri hanno già fornito risposte codice in modo mi fermo qui.

Suppongo che

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

è una stringa.

Non si può assegnare una stringa per this.value perché il tipo di this.value è T e potrebbe essere qualsiasi cosa, come ad esempio i tipi a cui le stringhe non sono cedibili.

Una soluzione è quella di rimuovere il parametro generico e fare value una stringa, e quindi fornire diversi modi di accedervi, che analizzano bools, galleggianti, o qualsiasi altra cosa, come richiesto.

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

// etc

Sembra che si sta cercando di assegnare una stringa (configsettings.SettingGroups[heading].Settings[key].RawValue) al membro generico. Avrete bisogno di fornire un modo per convertire la stringa tipo T - di solito attraverso casting. Ad esempio:

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

In questa riga:

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

si sta impostando una variabile di tipo T ad un valore di stringa. Il metodo rawValue restituisce una stringa. È necessario lanciare esplicitamente di tipo T.

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

è una T davvero solo sarà solo valori senza i costruttori? Potreste essere in grado di fare che esplicita ed evitare il oggetto di fusione, se si vuole evitare che per qualche motivo.

Prova a

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

se avete i vostri valori di configurazione memorizzati come stringhe e desidera convertito nel tipo di destra. Questo funziona solo per la maggior parte dei tipi primitivi come Int32, doppio, ecc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top