Bir yöntemin dönüş türünü nasıl genel hale getirebilirim?


166

Bir dize, bool, int veya çift geri verebilir böylece bu yöntemi genel yapmak için bir yolu var mı? Şu anda, bir dize döndürüyor, ancak yapılandırma değeri olarak "true" veya "false" bulabiliyorsa, örneğin bir bool döndürmek istiyorum.

    public static string ConfigSetting(string settingName)
    {  
         return ConfigurationManager.AppSettings[settingName];
    }

Her ayarın ne tür olduğunu bilmenin bir yolu var mı?
thecoshman

2
Bence gerçekten sormak istediğiniz soru "Uygulama yapılandırmamı nasıl güçlü yazabilirim?" Bununla birlikte, düzgün bir cevap yazmak için çok uzun zaman geçti.
Simon

Yah, ideal olarak türü yönteme geçirmek istemiyorum. Sadece bahsettiğim 4 tip olacak. Eğer "true" / "false" ayarlıysa, bu işlevin bir boole döndürmesini istiyorum (yönteme geçirmeye gerek kalmadan), muhtemelen int ve double'ı sadece double'a birleştirebilirim ve diğer her şey bir dize olmalıdır. Yanıtlanan şey zaten işe yarayacak, ancak her seferinde türü geçmem gerekiyor, ki bu muhtemelen iyi.
MacGyver

3
Yorumunuz , ayar adı anahtarı için alınan gerçek verilere dayanarak çalışma zamanında güçlü yazılan bir boole (veya dize veya int veya neye sahip olduğunuz) döndürecek bir yöntem istiyor gibi görünüyor . C # bunu sizin için yapmayacak; derleme zamanında bu değerin türünü bilmenin bir yolu yoktur. Başka bir deyişle, statik yazım değil, dinamik yazımdır. dynamicAnahtar kelimeyi kullanırsanız C # bunu sizin için yapabilir . Bunun için bir performans maliyeti var, ancak bir yapılandırma dosyasını okumak için performans maliyeti neredeyse kesinlikle önemsizdir.
phoog

Yanıtlar:


354

Bunu genel bir yöntem haline getirmeniz gerekir, örneğin:

public static T ConfigSetting<T>(string settingName)
{  
    return /* code to convert the setting to T... */
}

Ancak arayanın beklediği türü belirtmesi gerekir. Daha sonra Convert.ChangeType, ilgili tüm türlerin desteklendiğini varsayarak potansiyel olarak kullanabilirsiniz :

public static T ConfigSetting<T>(string settingName)
{  
    object value = ConfigurationManager.AppSettings[settingName];
    return (T) Convert.ChangeType(value, typeof(T));
}

Tüm bunların iyi bir fikir olduğuna tamamen ikna olmadım, unutmayın ...


21
/ * kodu ayarı T ... * /
biçimine

1
Bu, almak istediğiniz ayarın türünü bilmenizi gerektirmez, bu mümkün olmayabilir.
thecoshman

2
@thecoshman: Olurdu, ama eğer vermediyseniz, döndürülen değerle ne yaparsınız?
George Duckett

5
Bu cevap elbette doğru taşımaktadır ve Sağlama, OP'ın isteğini not olarak, bu ayrı yöntemlerle (eski yaklaşım muhtemelen bahsetmemiz olsa ConfigSettingString, ConfigSettingBool, vs.) kısa olacaktır yöntem organlarının avantajı daha net ve daha iyi odaklanmış .
phoog

4
Bu önerilmiyorsa, genel iade türlerinin amacı nedir?
bobbyalex

29

Şunları kullanabilirsiniz Convert.ChangeType():

public static T ConfigSetting<T>(string settingName)
{
    return (T)Convert.ChangeType(ConfigurationManager.AppSettings[settingName], typeof(T));
}

13

Bunu yapmanın birçok yolu vardır (OP'nin sorununa özgü olarak öncelik sırasına göre listelenmiştir)

  1. Seçenek 1: Düz yaklaşım - Tek bir genel işleve sahip olmak yerine beklediğiniz her tür için birden çok işlev oluşturun.

    public static bool ConfigSettingInt(string settingName)
    {  
         return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]);
    }
  2. Seçenek 2: Süslü dönüştürme yöntemlerini kullanmak istemediğinizde - Değeri nesneye ve sonra da genel türe dönüştürün.

    public static T ConfigSetting<T>(string settingName)
    {  
         return (T)(object)ConfigurationManager.AppSettings[settingName];
    }

    Not - Oyuncular geçerli değilse (durumunuz) bir hata atar. Eğer tür döküm hakkında emin değilseniz, bu seçenek 3 için gitmek bunu tavsiye etmem.

  3. Seçenek 3: Tip güvenliğine sahip genel - Tip dönüştürmeyi yönetmek için genel bir işlev oluşturun.

    public static T ConvertValue<T,U>(U value) where U : IConvertible
    {
        return (T)Convert.ChangeType(value, typeof(T));
    } 

    Not - T beklenen türdür, burada nerede kısıtlamaya dikkat edin (bizi hatalardan kurtarmak için U tipi IConvertible olmalıdır)


4
Üçüncü seçeneği neden jenerik hale getirelim U? Bunu yapmanın bir anlamı yok ve yöntemi çağırmayı zorlaştırıyor. Sadece kabul et IConvertible. Sorulan soruya cevap vermediği sürece, bu soru için ikinci seçeneği dahil etmeye değer olduğunu sanmıyorum. Muhtemelen ilk seçenekte yöntemi yeniden adlandırmalısınız ...
Jon Skeet

7

Yöntemin dönüş değerinin türünü, arama sırasında yönteme ilettiğiniz Genel türe dönüştürmeniz gerekir.

    public static T values<T>()
    {
        Random random = new Random();
        int number = random.Next(1, 4);
        return (T)Convert.ChangeType(number, typeof(T));
    }

Bu yöntemle döndürdüğünüz değer için cast türünde bir tür geçirmeniz gerekir.

Geçirdiğiniz genel türe dönüştürülebilir türden olmayan bir değer döndürmek isterseniz, kodu değiştirmeniz veya yöntemin dönüş değeri için döndürülebilir bir tür ilettiğinizden emin olmanız gerekebilir. Bu nedenle, bu yaklaşım önerilmez.


Spot on - benim için son satır return (T)Convert.ChangeType(number, typeof(T));tam olarak eksik olduğum şeydi - şerefe
Greg Trevellick

1

Bir işlev oluşturun ve genel türdeki put parametresini iletin.

 public static T some_function<T>(T out_put_object /*declare as Output object*/)
    {
        return out_put_object;
    }

Bu aslında birkaç kullanım durumu için oldukça akıllı. Veriyi veritabanından çıkarmak gibi. T tipi verilerin bir listesini alacağınızı biliyorsunuz. Yükleme yöntemi, ŞİMDİ ne ​​tür T istediğinizi bilmiyor. Bu yüzden sadece yeni bir Liste <WantedObject> geçirin ve yöntem işini yapabilir ve iade etmeden önce listeyi doldurabilir. Güzel!
Marco Heumann

0

Lütfen aşağıdaki kodu deneyin:

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

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

Bunu kodum boyunca gerçekleştiriyordum ve bir yönteme koymak için bir yol istedi. Benim dönüş değeri için Convert.ChangeType kullanmak zorunda değildi çünkü bu paylaşmak istiyorum. Bu en iyi uygulama olmayabilir ama benim için çalıştı. Bu yöntem, bir dizi genel tür ve dizinin sonuna eklenecek bir değer alır. Daha sonra dizi, soyulmuş ilk değerle kopyalanır ve yönteme alınan değer dizinin sonuna eklenir. Son şey, genel diziyi döndürmektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.