确保 Type 实例代表可从某些 class 分配的类型
Make sure Type instance represents a type assignable from certain class
我主要是一名 Java 程序员,所以这将是 "what is this thing from Java equivalent to in C#" 问题之一。所以,在Java中,你可以在编译时限制一个Class类型的参数来扩展某个超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);
}
所以,在这个例子中,我不关心 class 'type' 变量代表什么,只要它是从 BaseClass 派生的,所以一旦我创建了一个例如,可以调用 Foo().
不是有效 C# 代码的部分(而是一些 Java 模型)是 "generic" 类型 classes:Type 和 Type : 基础Class>.
根据我的理解,你说的是 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.
编辑:
这是你的例子。现在,如果您尝试使用与 BaseClass 及其派生的 class 不同的内容调用 BaseClassUtil.CallFoo<T>
,您将收到编译错误。这里full example in dotNetFiddle。所以棘手的部分是你的 class 的限制应该发生在 Util class
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
显然在运行时它是微不足道的,但语言在编译时不支持它。
我主要是一名 Java 程序员,所以这将是 "what is this thing from Java equivalent to in C#" 问题之一。所以,在Java中,你可以在编译时限制一个Class类型的参数来扩展某个超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);
}
所以,在这个例子中,我不关心 class 'type' 变量代表什么,只要它是从 BaseClass 派生的,所以一旦我创建了一个例如,可以调用 Foo().
不是有效 C# 代码的部分(而是一些 Java 模型)是 "generic" 类型 classes:Type
根据我的理解,你说的是 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.
编辑:
这是你的例子。现在,如果您尝试使用与 BaseClass 及其派生的 class 不同的内容调用 BaseClassUtil.CallFoo<T>
,您将收到编译错误。这里full example in dotNetFiddle。所以棘手的部分是你的 class 的限制应该发生在 Util class
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
显然在运行时它是微不足道的,但语言在编译时不支持它。