簡體   English   中英

確保Type實例代表可從某些類分配的類型

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

我主要是Java程序員,所以這將是“ Java等同於C#的東西”的問題之一。 因此,在Java中,您可以在編譯時限制Class類型參數以擴展某些超類,如下所示:

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#中完成? 我知道您可以使用“ where T:BaseClass”,但這僅在您有實例T時適用。當您只有Type實例時呢?

編輯:

為了說明,這是我想做的:

組件#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()。

不是有效的C#代碼(而是一些Java樣機)的部分是“通用”類型類:Type <T>和Type <? :BaseClass>。

據我了解,您在談論泛型類型約束

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

這是另一篇文章: 類型參數的約束(C#編程指南)

定義通用類時,可以對實例化類時客戶端代碼可用於類型參數的類型類型施加限制。 如果客戶端代碼嘗試使用約束不允許的類型實例化您的類,則結果是編譯時錯誤。

編輯:

這是你的例子。 現在,如果您嘗試使用不同於BaseClass及其派生類的方式調用BaseClassUtil.CallFoo<T> ,您將收到編譯錯誤。 是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");
        }

    }

不,沒有辦法在編譯時強制將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

顯然,在運行時這很簡單,但是語言在編譯時不支持此功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM