Există o modalitate de a face această metodă generică, astfel încât să pot returna un șir de caractere, bool, int sau double? În momentul de față, returnează un șir de caractere, dar dacă este capabil să găsească „true” sau „false” ca valoare de configurare, aș dori să returneze un bool, de exemplu.
public static string ConfigSetting(string settingName)
{
return ConfigurationManager.AppSettings[settingName];
}
Trebuie să o faci o metodă generică, așa cum ar fi aceasta:
public static T ConfigSetting<T>(string settingName)
{
return /* code to convert the setting to T... */
}
Dar apelant va trebui să specifice tipul pe care îl așteaptă. În acest caz, ați putea utiliza Convert.ChangeType
, , presupunând că toate tipurile relevante sunt acceptate:
public static T ConfigSetting<T>(string settingName)
{
object value = ConfigurationManager.AppSettings[settingName];
return (T) Convert.ChangeType(value, typeof(T));
}
Nu sunt pe deplin convins că toate astea sunt o idee bună, dar…
- 23
- /* cod pentru a converti setarea în T… */ și aici urmează întregul roman 🙂 – > .
- Nu ar fi nevoie ca acest lucru să cunoști tipul de setare pe care dorești să-l obții, ceea ce s-ar putea să nu fie posibil. – > .
- @thecoshman: Ar fi, dar dacă nu ai ști, atunci ce faci cu valoarea returnată? – > .
- În timp ce acest răspuns este, desigur, corect și, după cum observați, satisface cererea OP-ului, probabil că merită menționat faptul că vechea abordare a metodelor separate (
ConfigSettingString
, ,ConfigSettingBool
, , etc.) are avantajul unor corpuri de metode care vor fi mai scurte, mai clare și mai bine focalizate. – > . - Dacă acest lucru nu este recomandat, atunci care este scopul tipurilor de returnare generice? – > .
Ați putea folosi Convert.ChangeType()
:
public static T ConfigSetting<T>(string settingName)
{
return (T)Convert.ChangeType(ConfigurationManager.AppSettings[settingName], typeof(T));
}
Există mai multe modalități de a face acest lucru(enumerate în funcție de prioritate, specifice problemei lui OP)
-
Opțiunea 1: Abordare directă – Creați mai multe funcții pentru fiecare tip pe care îl așteptați, în loc să aveți o singură funcție generică.
public static bool ConfigSettingInt(string settingName) { return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]); }
-
Opțiunea 2: Când nu doriți să folosiți metode sofisticate de conversie – Transformați valoarea în obiect și apoi în tip generic.
public static T ConfigSetting<T>(string settingName) { return (T)(object)ConfigurationManager.AppSettings[settingName]; }
Notă. Acest lucru va genera o eroare dacă castul nu este valid (cazul dvs.). Nu v-aș recomanda să faceți acest lucru dacă nu sunteți sigur de tipul de turnare, ci mai degrabă să alegeți opțiunea 3.
-
Opțiunea 3: Generică cu siguranță de tip – Creați o funcție generică pentru a gestiona conversia de tip.
public static T ConvertValue<T,U>(U value) where U : IConvertible { return (T)Convert.ChangeType(value, typeof(T)); }
Notă. T este tipul așteptat, observați constrângerea where (tipul lui U trebuie să fie IConvertible pentru a ne salva de erori).
- De ce să facem cea de-a treia opțiune generică în
U
? Nu are rost să o facem și face metoda mai greu de apelat. Acceptați pur și simpluIConvertible
în schimb. Nu cred că merită să includem a doua opțiune pentru această întrebare, având în vedere că nu răspunde la întrebarea pusă. De asemenea, ar trebui probabil să redenumiți metoda din prima opțiune… – > .
Trebuie să convertiți tipul valorii de returnare a metodei în tipul Generic pe care îl transmiteți metodei în timpul apelării.
public static T values<T>()
{
Random random = new Random();
int number = random.Next(1, 4);
return (T)Convert.ChangeType(number, typeof(T));
}
Trebuie să treceți un tip care este casabil pentru valoarea pe care o returnați prin metoda respectivă.
Dacă doriți să returnați o valoare care nu poate fi casată la tipul generic pe care îl treceți, ar trebui să modificați codul sau să vă asigurați că treceți un tip care poate fi casat pentru valoarea de returnare a metodei. Prin urmare, această abordare nu este recomandată.
- Exact – pentru mine, ultima linie
return (T)Convert.ChangeType(number, typeof(T));
a fost exact ceea ce îmi lipsea – noroc – > .
Creați o funcție și transmiteți parametrul put ca fiind de tip generic.
public static T some_function<T>(T out_put_object /*declare as Output object*/)
{
return out_put_object;
}
- Acest lucru este de fapt destul de inteligent pentru câteva cazuri de utilizare. Cum ar fi extragerea datelor dintr-o bază de date. Știți că veți obține o listă de date de tip T. Doar că metoda de încărcare nu știe ce tip de T doriți chiar ACUM. Așa că trebuie doar să treceți o nouă listă „WantedObject” la această metodă, iar metoda își poate face treaba și umple lista înainte de a o returna. Frumos! – > .
Vă rugăm să încercați codul de mai jos:
public T? GetParsedOrDefaultValue<T>(string valueToParse) where T : struct, IComparable
{
if(string.EmptyOrNull(valueToParse))return null;
try
{
// return parsed value
return (T) Convert.ChangeType(valueToParse, typeof(T));
}
catch(Exception)
{
//default as null value
return null;
}
return null;
}
private static T[] prepareArray<T>(T[] arrayToCopy, T value)
{
Array.Copy(arrayToCopy, 1, arrayToCopy, 0, arrayToCopy.Length - 1);
arrayToCopy[arrayToCopy.Length - 1] = value;
return (T[])arrayToCopy;
}
Efectuam acest lucru în tot codul meu și am vrut o modalitate de a-l pune într-o metodă. Am vrut să împărtășesc acest lucru aici pentru că nu a trebuit să folosesc Convert.ChangeType pentru valoarea de returnare. Este posibil să nu fie o practică optimă, dar a funcționat pentru mine. Această metodă primește o matrice de tip generic și o valoare care trebuie adăugată la sfârșitul matricei. Matricea este apoi copiată cu prima valoare eliminată, iar valoarea introdusă în metodă este adăugată la sfârșitul matricei. Ultimul lucru pe care îl returnez este matricea generică.
dynamic
cuvântul cheie. Există un cost de performanță pentru acest lucru, dar pentru citirea unui fișier de configurare, costul de performanță este aproape sigur nesemnificativ. – > Por phoog.