2016-12-12 3 views
8

Я в первую очередь программист на Java, так что это будет один из вопросов «что это такое из Java, эквивалентного C#». Таким образом, в Java, вы можете ограничить доступ типа класса аргумент во время компиляции продлить определенный супер-класса, например, так:Убедитесь, что экземпляр экземпляра представляет тип, назначаемый из определенного класса

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

и даже

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

Вы даже можете приковать несколько интерфейсов :

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

Как это делается на C#? Я знаю, что вы можете использовать «где T: BaseClass», но это применимо только тогда, когда у вас есть экземпляр T. Как насчет того, когда у вас есть экземпляр типа?

EDIT:

Для объяснения, вот что я хотел бы сделать:

СБОРКА # 1 (base.dll):

abstract class BaseClass { 
    abstract void Foo(); 
} 

СБОРКА # 2 (sub1.dll, ссылки base.dll):

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

СБОРКА # 3 (sub2.dll ссылки base.dll):

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

СБОРКА # 4 (main.dll ссылки 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); 
} 

Таким образом, в этом примере, я не волнует, что класс представляет собой переменную 'тип', до тех пор, он получен из BaseClass, поэтому, как только я создаю экземпляр, вы можете вызвать Foo().

Элементы, которые не являются кодом Vaild (а скорее некоторым Java-макетом), являются «универсальными» типами классов: Тип < T> и тип <? : BaseClass>.

ответ

2

Нет, нет никакого способа для обеспечения во время компиляции, что Type быть отнесена к универсальному типу.Если я правильно понимаю, что вы хотите:

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

Что означает:

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

Очевидно, во время выполнения это тривиальный, но язык не имеет никакой поддержки для этого во время компиляции.

2

Из того, что я понял, вы говорите о generic type constraint

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

Вот еще одна статья: 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:

Вот ваш пример. Теперь, если вы попытаетесь позвонить BaseClassUtil.CallFoo<T> с чем-то отличным от BaseClass и его производными классами, вы получите ошибку компиляции. Здесь full example in dotNetFiddle. Таким образом, сложная частью является ограничение вашего класса должно происходить в классе 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

Спасибо за ваш ответ, но я не уверен, что это соответствует моим потребностям. Проблематичной частью является часть класса «» - я не думаю, что это действительный синтаксис C#, и это проблема. Если бы это было так, то это, безусловно, решило бы мою проблему. Но я уверен, что это не так. – milin

+0

@milin Я написал вам небольшой пример. Надеюсь, что это очистит ваши сомнения. – mybirthname

+0

Я добавил пример того, что я хотел бы сделать. Я чувствую, что мои объяснения недостаточно ясны, потому что ваш пример об общих экземплярах, и у меня есть проблема с типичными экземплярами типа. – milin

Смежные вопросы