제네릭 유형이 문자열인지 테스트하는 가장 좋은 방법은 무엇입니까? (씨#)


95

모든 유형, 기본 또는 기타를 허용해야하는 일반 클래스가 있습니다. 이것의 유일한 문제는 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>();
    }
}

그러나 이것은 kludge처럼 느껴집니다. 문자열 케이스를 처리하는 더 좋은 방법이 있습니까?

답변:


162

default (string)은 string이 아니라 null입니다. 코드에 특별한 경우가 필요할 수 있습니다.

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

2
나는 그 해결책을 일찍 시도했지만 작동하지 않는다고 생각했지만 어리석은 일을 한 것 같습니다. 그리고 default (string) 반환 null을 지적 해 주셔서 감사합니다. 우리는 그 때문에 아직 오류가 발생하지 않았지만 사실입니다.
Rex M

1
@Matt Hamilton : +1,하지만 CodeInChaos에서 제안한대로 '(T) (object) String.Empty'를 반환하도록 답변을 업데이트해야합니다. 메서드 반환 유형이 제네릭이므로 문자열을 반환 할 수는 없습니다.
VoodooChild

2
[정보] 어떤 is키워드? 여기서 사용하지 않습니까?
Naveed Butt

지금은 불가능에 제네릭 및 할당 또는 직접 인스턴스화와 연산자를 적용, 그렇지 않습니다? 멋진 기능이 될 것입니다
후안 파블로 가르시아 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.