Genel bir türün dizge olup olmadığını test etmenin en iyi yolu? (C #)


96

İlkel olsun olmasın her türe izin vermesi gereken genel bir sınıfım var. Bununla ilgili tek sorun kullanmaktır default(T). Bir değer türü veya dizede varsayılanı çağırdığınızda, onu makul bir değerle başlatır (boş dize gibi). Bir default(T)nesneyi çağırdığınızda null döndürür. Çeşitli nedenlerden dolayı, ilkel bir tür değilse, o zaman null değil , türün varsayılan bir örneğine sahip olacağımızdan emin olmalıyız . İşte 1. girişim:

T createDefault()
{
    if(typeof(T).IsValueType)
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Problem - dizge bir değer türü değildir, ancak parametresiz bir kurucusu yoktur. Dolayısıyla mevcut çözüm şudur:

T createDefault()
{
    if(typeof(T).IsValueType || typeof(T).FullName == "System.String")
    {
        return default(T);
    }
    else
    {
        return Activator.CreateInstance<T>();
    }
}

Ama bu bir kludge gibi geliyor. İpli davayı halletmenin daha güzel bir yolu var mı?

Yanıtlar:


163

Default (string) 'in string.Empty değil null olduğunu unutmayın. Kodunuzda özel bir durum isteyebilirsiniz:

if (typeof(T) == typeof(String)) return (T)(object)String.Empty;

2
Bu çözümü daha önce denediğimi düşündüm ve işe yaramadı, ama aptalca bir şey yapmış olmalıyım. Ve default (string) 'in null döndürdüğünü belirttiğiniz için teşekkürler, bu yüzden henüz bir hatayla karşılaşmadık, ama bu doğru.
Rex M

1
@Matt Hamilton: +1, ancak cevabınızı CodeInChaos tarafından önerildiği gibi '(T) (object) String.Empty' döndürmek için güncellemelisiniz çünkü yöntem dönüş türü geneldir, sadece string döndüremezsiniz.
VoodooChild

2
isAnahtar kelime ne olacak ? Bunun burada bir faydası yok mu?
Naveed Butt

Şu anda is operatörünü jenerik ve atama veya doğrudan örnekleme ile uygulamak mümkün değil, değil mi? Harika bir özellik olacak
Juan Pablo Garcia Coello

14
if (typeof(T).IsValueType || typeof(T) == typeof(String))
{
     return default(T);
}
else
{
     return Activator.CreateInstance<T>();
}

Denenmemiş ama akla ilk gelen şey.


4

TypeCode numaralandırmasını kullanabilirsiniz . Bu sınıfın bir örneğinin tür kodunu elde etmek için IConvertible arabirimini uygulayan sınıflarda GetTypeCode yöntemini çağırın. IConvertible Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime, Char ve String tarafından uygulanır, böylece bunu kullanarak ilkel türleri kontrol edebilirsiniz. " Genel Tip Kontrolü " hakkında daha fazla bilgi .


2

Şahsen, yöntem aşırı yüklemeyi seviyorum:

public static class Extensions { 
  public static String Blank(this String me) {      
    return String.Empty;
  }
  public static T Blank<T>(this T me) {      
    var tot = typeof(T);
    return tot.IsValueType
      ? default(T)
      : (T)Activator.CreateInstance(tot)
      ;
  }
}
class Program {
  static void Main(string[] args) {
    Object o = null;
    String s = null;
    int i = 6;
    Console.WriteLine(o.Blank()); //"System.Object"
    Console.WriteLine(s.Blank()); //""
    Console.WriteLine(i.Blank()); //"0"
    Console.ReadKey();
  }
}


-6

String için tartışma burada çalışmıyor.

Çalışması için jeneriklerin aşağıdaki koda sahip olması gerekiyordu -

   private T createDefault()
    { 

        {     
            if(typeof(T).IsValueType)     
            {         
                return default(T);     
            }
            else if (typeof(T).Name == "String")
            {
                return (T)Convert.ChangeType(String.Empty,typeof(T));
            }
            else
            {
                return Activator.CreateInstance<T>();
            } 
        } 

    }

3
Ada Stringgöre test etmek , özellikle bir ad alanıyla ilgili olmadan kötüdür. Ve senin dönüştürme şeklinden de hoşlanmıyorum.
CodesInChaos
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.