2013-01-09 2 views
15

저는 .NET 녀석입니다. 그래서 처음에는 몇 가지 Java 개념에 대한 이해를 표명하겠습니다. 내가 잘못하면 저를 수정하십시오.. Java 형식의 클래스 <>에 해당하는 .Net?

의 .NET where 제한과 유사
class GenericClass< ? extends IInterface> { ... } 

... :

class GenericClass<T> where T: IInterface { ... } 

자바의 Class 클래스 유형을 설명하고

자바 제네릭 경계 와일드 카드의 개념을 지원 Type 클래스

과 같습니다.

지금까지 그렇게 좋았습니다. 그러나 Java generic typed Class<T>에 가까운 동등 함을 찾을 수 없습니다. 여기서 T는 바운드 와일드 카드입니다. 이는 기본적으로 Class이 나타내는 유형에 제한을 부과합니다.

Java로 예를 들어 보겠습니다.

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 

Assembly assy = GetAssembly();    //unimportant 

Type customClass = assy.GetType(custSortclassName); 
if(!customClass.IsSubclassOf(typeof(IExternalSort))){ 
    throw new InvalidOperationException(...); 
} 
IExternalSort impl = (IExternalSort)Activator.CreateInstance(customClass); 

Java 버전이 나에게 청소기 같습니다

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 
Class<? extends IExternalSort> customClass 
    = Class.forName("MyExternalSort") 
     .asSubclass(IExternalSort.class); //this checks for correctness 

IExternalSort impl = customClass.newInstance(); //look ma', no casting! 

내가 .NET에서 얻을 수있는 가장 가까운이 같은 것입니다. . NET을 개선하는 방법이 있습니까?

String custSortclassName = GetClassName(); 
Assembly assy = GetAssembly(); 
Type customClass = assy.GetType(custSortclassName); 

IExternalSort impl = Activator.CreateInstance(customClass) as IExternalSort; 
if(impl==null) throw new InvalidOperationException(...); 

을하지만, 여기에 당신을 위해 문제가 될 수 있습니다 그것의 유형을 확인하기 전에 인스턴스를 만드는거야 :

+1

이것은 약간 쉽지만 간단히 where 제한에'new()'제약 조건을 추가하는 것이 불가능할까요? 'MyExternalSort : IExternalSort T : IExternalSort, new()'와 같은 것을 사용하고'var impl = new T();'를 사용합니까? 개인적으로 나는 그러한 시나리오에서 동일한 인터페이스를 구현하는 유형의 인스턴스를 생성하기 위해 팩토리 패턴을 사용할 것이다. – Carsten

+0

Java generics에 대해서는 잘 모릅니다. 그러나 JVM 지원이 다르게 구현되어 있고 .NET generics가 지원하지 않는 여러 가지 기능을 지원한다는 것을 알고 있습니다. 모든 것에 대해 똑같은 "동등한"것을 기대하지 마십시오. – jalf

+0

@Aschratt이 글은 제 질문과 관련이없는 것 같습니다. 이 트릭은 모든 유형 정보가 컴파일 타임에 알려지면 유용 할 수 있지만 MyExternalSort 유형은 런타임 전까지 알 수 없습니다. 정렬 라이브러리의 클라이언트가 구현할 수 있으며 이름으로 만 지정됩니다. –

답변

2

System.Type을 사용하면 Java 구문과 매우 흡사하게됩니다. 참고

:Type.IsSubclassOf이 유형의 인터페이스를 구현하는 경우 테스트하는 데 사용할 수 없습니다가 - MSDN에 링크 된 문서를 참조하십시오. 대신 Type.IsAssignableFrom을 사용할 수 있습니다. 아래 코드를 참조하십시오. 인터페이스 분산을 사용

using System; 

class Type<T> 
{ 
    readonly Type type; 

    public Type(Type type) 
    { 
     // Check for the subtyping relation 
     if (!typeof(T).IsAssignableFrom(type)) 
      throw new ArgumentException("The passed type must be a subtype of " + typeof(T).Name, "type"); 

     this.type = type; 
    } 

    public Type UnderlyingType 
    { 
     get { return this.type; } 
    } 
} 

static class TypeExtensions 
{ 
    public static Type<T> AsSubclass<T>(this System.Type type) 
    { 
     return new Type<T>(type); 
    } 
} 

// This class can be expanded if needed 
static class TypeWrapperExtensions 
{ 
    public static T CreateInstance<T>(this Type<T> type) 
    { 
     return (T)Activator.CreateInstance(type.UnderlyingType); 
    } 
} 

추가 개선

(성능을 평가 한 후에 만 ​​생산 코드에 사용되어야한다. A (동시!) 캐시 사전 ConcurrentDictionary<System.Type, IType<object> 사용함으로써 개선 될 수있다)

Covariant type parameters, C# 4.0에서 도입 된 기능 및 추가 유형 interface IType<out T> (Type<T>이 구현 됨)을 사용하면 다음과 같은 것을 만들 수 있습니다.

// IExternalSortExtended is a fictional interface derived from IExternalSort 
IType<IExternalSortExtended> extendedSort = ... 
IType<IExternalSort> externalSort = extendedSort; // No casting here, too. 

하나에도 수 :

using System; 

interface IType<out T> 
{ 
    Type UnderlyingType { get; } 
} 

static class TypeExtensions 
{ 
    private class Type<T> : IType<T> 
    { 
     public Type UnderlyingType 
     { 
      get { return typeof(T); } 
     } 
    } 

    public static IType<T> AsSubclass<T>(this System.Type type) 
    { 
     return (IType<T>)Activator.CreateInstance(
      typeof(Type<>).MakeGenericType(type) 
     ); 
    } 
} 

static class TypeWrapperExtensions 
{ 
    public static T CreateInstance<T>(this IType<T> type) 
    { 
     return (T)Activator.CreateInstance(type.UnderlyingType); 
    } 
} 

그래서 그 사람이 할 수있는 관계가없는 인터페이스 InterfaceA과 같은 InterfaceB 사이 (명시 적) 캐스트 :

var x = typeof(ConcreteAB).AsSubclass<InterfaceA>(); 
var y = (IType<InterfaceB>)x; 

하지만 그건 좀 운동의 목적을 패배 .

0

당신은 "로"연산자를 사용하여 약간 더 예쁜 버전을 얻을 수 있습니다.

+1

'as '연산자도 캐스트를 수행합니다. 유일한 차이점은 캐스트가 성공하지 못하면 예외를 throw하지 않는다는 것입니다. 이것은 실제로 더 쉽게하지 않습니다. – Carsten

1

제네릭 선언 - 사이트 분산, 형식 매개 변수의 분산 고정되어 있습니다. 우리가 선언 List<E>이 그래서 일단

자바는 우리가 그것을 3 가지 방법

List<Number>   // invariant, read/write 
List<+Number>   // covariant, read only 
List<-NUmber>   // contravariant, write only 

두 가지 접근 방식에 대한 장점과 단점이 있습니다

를 사용할 수, 사용 현장의 분산이다. 사용 사이트 접근법은 분명히 더 강력하지만 프로그래머에게 너무 어렵다는 평판을 얻었습니다. 코드는 다음의 몇 가지가 정말 추한하게되면 나는 실제로
List<Integer> integers = ...; 
List<+Number> numbers = integers; // covariant 

불행하게도, 자바가 절대적으로 끔찍한 구문을 발명 파악하는 것이 매우 쉽다

List<? extends Number> // i.e. List<+Number> 

생각합니다. 당신은 그것을 극복하는 법을 배워야합니다.

이제 선언 사이트 캠프에서 같은 클래스에서 3 가지 차이를 어떻게 달성합니까? 더 많은 유형을 사용하면 ReadOnlyList<out E>, WriteOnlyList<in E>List<E>을 모두 확장 할 수 있습니다. 이것은 그리 나쁘지는 않지만 더 나은 디자인이라고 말할 수 있습니다. 그러나 더 많은 유형 매개 변수가 있으면 추한 될 수 있습니다. 그리고 클래스의 디자이너가 변형되어 사용되기를 기대하지 않는다면, 클래스의 사용자는 변형 된 방법을 사용할 수 없습니다.

+0

내 생각에 나는 당신의 대답이 무엇인지에 대해 이해하고 있다고 생각한다. 그러나 그것은 내 [이 (최신) 질문] (http://stackoverflow.com/q/14277441/11545)과 관련이 있지만. 어쩌면 당신이 볼 수 있습니다. –

0

당신은 다음과 같이 확장 메서드를 작성 시도 할 수 있습니다 :

static class TypeExtension 
    { 
     public static I NewInstanceOf<I>(this Type t) 
      where I: class 
     { 
      I instance = Activator.CreateInstance(t) as I; 
      if (instance == null) 
       throw new InvalidOperationException(); 
      return instance; 
     } 
    } 

후 다음과 같은 방식으로 사용할 수있는 : 확장 방법 & 사용자 정의 래퍼 클래스를 사용

String custSortclassName = GetClassName(); //only known at runtime, 
              // e.g. it can come from a config file 

Assembly assy = GetAssembly(); 
Type customClass = assy.GetType(custSortclassName);    

IExternalSort impl = customClass.NewInstanceOf<IExternalSort>(); 
관련 문제