2016-12-12 29 views
8

Jestem przede wszystkim programistą Java, więc byłby to jeden z tych pytań "co to jest z Java odpowiednik w C#". Tak więc, w Javie, można powstrzymać typu klasy argumentu w czasie kompilacji rozszerzyć pewną super-klasę, tak jak poniżej:Upewnij się, że instancja Type reprezentuje typ przypisany do konkretnej klasy

public <T extends BaseClass> void foo(Class<T> type) { 
    ... 
} 

a nawet

public <T extends BaseClass> T foo(Class<T> type) { 
    ... 
} 

Można nawet łańcucha wiele interfejsów :

public <T extends BaseClass & BaseInterface1 & BaseInterface2> void foo(Class<T> type) { 
    ... 
} 

Jak to zrobić w języku C#? Wiem, że możesz użyć "where T: BaseClass", ale dotyczy to tylko sytuacji, gdy masz instancję T. A co, gdy masz tylko instancję typu?

EDIT:

Dla wyjaśnienia, tutaj jest to, co chciałbym zrobić:

MONTAŻ # 1 (base.dll):

abstract class BaseClass { 
    abstract void Foo(); 
} 

MONTAŻ # 2 (sub1.dll, referencje base.dll):

class SubClass1 : BaseClass { 
    void Foo() { 
     // some code 
    } 
} 

MONTAŻ nr 3 (sub2.dll odniesienia base.dll):

class SubClass2 : BaseClass { 
    void Foo() { 
     // some other code 
    } 
} 

MONTAŻ # 4 (main.dll odniesienia base.dll):

class BaseClassUtil { 
    static void CallFoo(Type<T> type) where T : BaseClass { 
     T instance = (T)Activator.CreateInstance(type); 
     instance.Foo(); 
    } 
} 

public static void Main(String[] args) { 
    // Here I use 'args' to get a class type, 
    // possibly loading it dynamically from a DLL 

    Type<? : BaseClass> type = LoadFromDll(args); // Loaded from DLL 

    BaseClassUtil.CallFoo(type); 
} 

Tak więc, w tym przykładzie, nie obchodzi mnie, co klasa zmienna 'typ' oznacza, o ile pochodzi od BaseClass, więc gdy utworzę instancję, można wywołać funkcję Foo().

Części, które nie są vaild C# kod (ale raczej niektóre Java makieta) są "ogólne" Klasy Type: Type < T> i Type <? : BaseClass>.

Odpowiedz

2

Nie, nie ma sposobu, aby wymusić w czasie kompilacji, że Type są przypisane do typu rodzajowego.Jeśli dobrze rozumiem, co chcesz, to:

void Foo<T>(Type type) { ... } //compile time error if an instace typed `type` is not assignable to `T`. 

Co oznacza:

void Foo<IFormattable>(typeof(string)); //ok 
void Foo<IDisposable>(typeof(string)); //compile time error 

Widocznie przy starcie jest błahe, ale język nie obsługuje tego w czasie kompilacji.

2

Z tego, co zrozumiałem, mówisz generic type constraint

public void Foo<T>(Type type) where T:BaseClass, BaseInterface1, BaseInterface2 
{ 
    //your code 
} 

Oto kolejny artykuł: Constraints on Type Parameters (C# Programming Guide)

When you define a generic class, you can apply restrictions to the kinds of types that client code can use for type arguments when it instantiates your class. If client code tries to instantiate your class by using a type that is not allowed by a constraint, the result is a compile-time error.

EDIT:

tutaj swoje przykładem. Teraz, jeśli spróbujesz wywołać BaseClassUtil.CallFoo<T> z czymś innym niż BaseClass i jego klas pochodnych, otrzymasz błąd kompilacji. Tutaj full example in dotNetFiddle. Więc Najtrudniejszą częścią jest ograniczenie swojej klasie powinno się zdarzyć w klasie Util

public static void Main(string[] args) 
    { 
     //so your LoadFromDll method should return Type. Type doesn't have generic implementation ! 
     Type type = typeof(SubClass1); 

     BaseClassUtil.CallFoo<BaseClass>(type); 

     Type type2 = typeof(SubClass2); 
     //you can write BaseClassUtil.CallFoo<SubClass2>(type2); if you want 
     BaseClassUtil.CallFoo<BaseClass>(type2); 
    } 

    public class BaseClassUtil 
    { 
     public static void CallFoo<T>(Type type) where T : BaseClass 
     { 
      T instance = (T)Activator.CreateInstance(type); 
      instance.Foo(); 
     } 
    } 
    public class TestClass 
    { 
     public int ID { get; set; } 

    } 

    public abstract class BaseClass 
    { 
     public abstract void Foo(); 
    } 

    public class SubClass1 : BaseClass 
    { 
     public override void Foo() 
     { 
      Console.WriteLine("SubClass 1"); 
     } 
    } 

    public class SubClass2 : BaseClass 
    { 
     public override void Foo() 
     { 
      Console.WriteLine("SubClass 2"); 
     } 

    } 
+0

Dziękuję za odpowiedź, ale nie jestem pewien, czy odpowiada moim potrzebom. Problematyczna część to część "Class " - nie sądzę, że jest to poprawna składnia C# - i to jest cały problem. Jeśli tak, to z pewnością rozwiąże mój problem. Ale jestem prawie pewien, że to nie jest ... – milin

+0

@milin Napisałem ci mały przykład Mam nadzieję, że to rozwiąże twoje wątpliwości – mybirthname

+0

Dodałem przykład, co chciałbym zrobić - czuję, że moje wyjaśnienie nie było wystarczająco jasne, ponieważ twój przykład dotyczy o ogólnych wystąpieniach i mam problem z typowymi instancjami Type. – milin