测试泛型类型是否为字符串的最佳方法?(C#)


93

我有一个通用类,应允许任何类型,原始或其他类型。唯一的问题是使用default(T)。当您对值类型或字符串调用default时,它将初始化为一个合理的值(例如空字符串)。调用default(T)对象时,它返回null。由于各种原因,我们需要确保它不是原始类型,那么我们将拥有该类型的默认实例,而不是 null。这是尝试1:

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

问题-字符串不是值类型,但是它没有无参数构造函数。因此,当前的解决方案是:

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

但这感觉就像是在跳动。有没有更好的方法来处理字符串大小写?

Answers:


161

请记住,default(string)为null,而不是string.Empty。您可能需要在代码中使用特殊情况:

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

2
我以为我早些时候尝试过该解决方案,但是它没有用,但是我一定做得有些愚蠢。并感谢您指出default(string)返回null,因此我们尚未遇到错误,但这是事实。
Rex M 2010年

1
@Matt Hamilton:+1,但是您应该更新您的答案以按照CodeInChaos的建议返回'(T)(object)String.Empty',因为方法的返回类型是通用的,您不能只返回字符串。
VoodooChild

2
怎么样的is关键字?这不是在用吗?
Naveed Butt 2014年

目前无法应用具有泛型和赋值或直接实例化的is运算符,不是吗?这将是一个很酷的功能
Juan Pablo Garcia Coello

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

未经测试,但想到的第一件事。


4

您可以使用TypeCode枚举。在实现IConvertible接口的类上调用GetTypeCode方法,以获取该类实例的类型代码。IConvertible由Boolean,SByte,Byte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal,DateTime,Char和String实现,因此您可以使用此方法检查基本类型。有关“ 通用类型检查 ”的更多信息。


2

就个人而言,我喜欢方法重载:

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的讨论在这里不起作用。

我必须使用以下泛型代码才能使其正常工作-

   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
String按名称进行测试(尤其是不考虑名称空间)是不好的。而且我也不喜欢您转换的方式。
CodesInChaos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.