简体   繁体   English

确保Type实例代表可从某些类分配的类型

[英]Make sure Type instance represents a type assignable from certain class

I'm primarily a Java programmer, so this would be one of those "what is this thing from Java equivalent to in C#" questions. 我主要是Java程序员,所以这将是“ Java等同于C#的东西”的问题之一。 So, in Java, you can restrain a Class type argument at compile time to extend a certain super-class, like so: 因此,在Java中,您可以在编译时限制Class类型参数以扩展某些超类,如下所示:

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

and even 乃至

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

You can even chain multiple interfaces: 您甚至可以链接多个接口:

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

How is this done in C#? 如何在C#中完成? I know you can use "where T : BaseClass", but this is only applicable when you have an instance T. What about when you only have a Type instance? 我知道您可以使用“ where T:BaseClass”,但这仅在您有实例T时适用。当您只有Type实例时呢?

EDIT: 编辑:

For explanation, here is what I would like to do: 为了说明,这是我想做的:

ASSEMBLY #1 (base.dll): 组件#1(base.dll):

abstract class BaseClass {
    abstract void Foo();
}

ASSEMBLY #2 (sub1.dll, references base.dll): 组件#2(sub1.dll,引用base.dll):

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

ASSEMBLY #3 (sub2.dll, references base.dll): 组件#3(sub2.dll,引用base.dll):

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

ASSEMBLY #4 (main.dll, references base.dll): 大会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);
}

So, in this example, I don't care what class the 'type' variable represents, as long as it is derived from BaseClass, so once I create an instance, can call Foo(). 因此,在此示例中,我不在乎“类型”变量表示什么类,只要它是从BaseClass派生的,那么一旦创建实例,就可以调用Foo()。

The parts that are not vaild C# code (but rather some Java mockup) are the "generic" Type classes: Type<T> and Type<? 不是有效的C#代码(而是一些Java样机)的部分是“通用”类型类:Type <T>和Type <? : BaseClass>. :BaseClass>。

From what I understood you are talking about generic type constraint 据我了解,您在谈论泛型类型约束

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

Here another article: Constraints on Type Parameters (C# Programming Guide) 这是另一篇文章: 类型参数的约束(C#编程指南)

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: 编辑:

Here your example. 这是你的例子。 Now if you try to call BaseClassUtil.CallFoo<T> with something different from BaseClass and his derived classes you will receive an compile error. 现在,如果您尝试使用不同于BaseClass及其派生类的方式调用BaseClassUtil.CallFoo<T> ,您将收到编译错误。 Here full example in dotNetFiddle . 是dotNetFiddle中的完整示例 So the tricky part is the restriction of your class should happen in the Util class 所以棘手的部分是您的类的限制应该在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");
        }

    }

No, there is no way to enforce at compile time that a Type be assignable to a generic type. 不,没有办法在编译时强制将Type分配给泛型类型。 If I understand correctly, what you want is: 如果我理解正确,那么您想要的是:

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

Which means: 意思是:

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

Evidently at runtime it is trival, but the language has no support for this at compile time. 显然,在运行时这很简单,但是语言在编译时不支持此功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM