2012-02-26 2 views
1

IEnumerator<string> 유형의 매개 변수를 사용하는 루틴이있는 경우 클래스 유형 인스턴스에 대한 참조와 참조를 구별 할 수있는 방법이 있습니까 박스형 값 유형 인스턴스에? 내가 아는 사람이 같은 루틴이있는 경우 :리플렉션없이 박스형 값 유형을 참조 유형과 구별 할 수 있습니까

 
void DoSomething<T>(T param) where T:IEnumerator 

T는 값 형식하거나 Object.ReferenceEquals(param, param)을 수행하여 반사를 사용하지 않고 참조 형식인지 여부를 알 수 있습니다. T이 클래스 유형이면 항상 true를 반환하고 값 유형 인 경우 항상 false를 반환합니다 (인터페이스를 구현하기 때문에 nullable 값 유형 일 수 없음). 반대로, DoSomething<IEnumerator<string>>(myListOfStrings.GetEnumerator())으로 전화를 걸려면 DoSomething이 Reflection을 사용하지 않고 다른 유형의 상자와 구별 된 동작을 구분할 수는 없습니다. 박싱 된 값 유형의 동작이 클래스 유형의 동작과 다른 리플렉션과 관련없는 방식이 있습니까?

부록 내가 IFoo를 구현하는 구조체 S1이 가정 문제를 명확히하기 위해, 나는 클래스와 동일한 인터페이스를 구현하고, 정확하게 같은 메소드와 필드가 C1 있습니다. 변수에 선언 된 유형이 IFoo 인 경우 해당 변수에서 참조하는 박스형 S1 인스턴스의 '자연스러운'동작은 C1의 인스턴스와 다르며 마찬가지로 을 참조하는 방식이 있습니까? 물론 다른 반품 Type 개체?

+2

저는 개인적으로 typeof (T) .IsValueType과 관련된 것을 사용합니다. 어쩌면 정적 generic 클래스에서 결과를 캐시했을 수도 있습니다 ... –

+0

왜 반사를 피하려고합니까? 또한 코드가 컴파일되지 않습니다. 'DoSomething > (myListOfStrings.GetEnumerator())'를 원하셨습니까? – svick

+0

@svick : IEnumeratable가 IEnumerator로 변경되었습니다. 감사. 조금 더 명확하게하기 위해 질문을 업데이트합니다. – supercat

답변

0

Type.IsValueType 속성을 사용할 수 있습니다. 다음은 예입니다 : 당신이 객체가있는 경우

static void Main() 
    { 
     DoSomething(10);   // True 
     DoSomething((object)10); // True 
     DoSomething(new Random()); // False 
    } 

    public static void DoSomething<T>(T arg) 
    { 
     bool isValueType = arg.GetType().IsValueType; 
     Console.WriteLine(isValueType); 
    } 
+0

Type.IsValueType은 Reflection을 수반하지만 그렇지 않습니까? – supercat

+0

@supercat :'Type.BaseType' 속성을 사용하여 유형 계층 구조를 살펴보고 부모가'(Type) RuntimeType.ValueType' 유형인지 확인합니다. 그 순간에 모든 기본 Type 개체가 이미 AppDomain에로드되므로이 방법으로 성능에 영향을 미치지는 않습니다. –

+0

아마도'GetType()'을 고려해야하고, 명시 적으로 참조 된'Type' 객체와 관련이있는 모든 것을 Reflection으로 생각하기 때문에 필자는 좀 더 명확해야합니다. 이 질문은 성과 중 하나는 아니지만 의미론이었습니다. 박스 화되지 않은 구조체의 동작은 동일한 메서드 및 필드가있는 클래스의 동작과 현저하게 다릅니다. 그러나 박스형 구조와 같은 메소드와 필드를 가진 클래스를 감안할 때'GetType()'이외의 다른 메소드를 구분할 수있는 방법이 있을까요? – supercat

4

e 정적 유형 (IEnumerator<string>을 같은) 일부 인터페이스이며 그것이 박스 값 형식인지 알고 싶어요, 당신은 간단하게 사용할 수 있습니다

e is ValueType 

System.ValueType은 .NET에서 모든 값 유형의 공통 기본 클래스입니다.

+0

구석의 경우는 IEnumerable을 구현하는 구조체입니다. 'IEnumerator '이 인용 된 이유를 알아보기 위해 잠시 시간을 보냈습니다. 항상 ref 유형입니다. +1은 가장 예쁜 대답을 위해 * 연산자가 사용하는 반사 형식을 숨 깁니다. 그것은 빠른 종류이며, 타입 정보가 매핑되지 않은 확률은 낮습니다. –

+0

@HansPassant : 내 질문은 boxed 구조체의 * behavior *가 필드와 메서드가 같은 클래스의 동작과 어떻게 다른지, 시스템이 값 유형이고 다른 클래스 유형이라고 말한 것입니다. 비 박스형 값 타입은 클래스 타입과 매우 다르게 동작하지만 박스형 값 타입 인스턴스는 'GetType'의 반환 값 이외에 식별 할 수있는 모든 방법으로 클래스 유형과 똑같이 작동합니다. 다른 차이점은 무엇입니까? – supercat

+0

무슨 뜻인지 확실치 않습니다. 권투의 행위는 그 자체로 꽤 엄청나 다. 구조체의 완전한 복사본은 GC 힙에서 할당되어야하는 메모리 덩어리에 임베드됩니다. 그 다음에 일어나는 일은 그 일에 비하면 아주 사소한 것입니다. 결국, 이제는 정규 참조 유형 객체와 매우 다르게 다루어지지 않는 클래스 객체입니다. –

0

이것이 "가시적 인 차이"로 간주 될지는 모르겠지만 구조체가 두 번 상자로 묶인 경우 두 개의 상자로 된 객체가 참조 평등하지 않을 것이라고 생각합니다. 구조체는 참조 ID를 갖지 않기 때문에 이는 의미가 있습니다. 그러나 나는 이것이 올 가능성이 높다고 생각하지 않는다.

아래 예제는 매우 고안되었습니다.

public class BoxDemo 
{ 
    public interface IFoo { } 
    public class CFoo : IFoo { } 
    public struct SFoo : IFoo { } 

    public static class TestBoxing 
    { 
     public static void dotest() 
     { 
      CFoo C = new CFoo(); 
      SFoo S = new SFoo(); 

      Debug.WriteLine(IsBoxedStruct(C, C)); // writes "false" 
      Debug.WriteLine(IsBoxedStruct(S, S)); // writes "true" 
     } 

     public static bool IsBoxedStruct(IFoo f1, IFoo f2) 
     { 
      return !object.ReferenceEquals(f1, f2); 
     } 
    } 
} 
+0

세 번째 선언문 'IFoo I = new SFoo()'를 추가하십시오. 'Debug.WriteLine (IsBoxedStruct (I, I));'매개 변수를 두 번 전달하여 테스트되는 것은 호출 된 함수가 박스형 구조를 받는지 여부가 아니라 호출자가 박스형 구조가 아닌지 여부입니다. – supercat

+0

덧붙여 말하자면, 값 유형 인스턴스 메소드가 'this'가 특정 박스형 인스턴스를 참조하는지 여부를 판단하는 것은 매우 어렵습니다. 그리고 'this'가 박스형인지 여부를 판단하기위한 값 유형 인스턴스가 없다는 것을 알고 있습니다. – supercat