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


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.