C#:是具有inheritance的generics类型的运算符

我有一个运算符比较generics类型的问题。

public interface ISomeInterface where T : SomeBaseClass{ } public class SomeClass : SomeBaseClass{ } 

现在我们想用is运算符检查类型。 我们有一个实现接口ISomeInterface的类的实例。

不幸的是,我们面临以下问题:

  // someObject is an Instance of a class implementing interface ISomeInterface bool isSomeBaseClass = someObject is ISomeInterface; // false bool isSomeClass = someObject is ISomeInterface; // true 

是否可以检查变量generics类型?

托比,提前谢谢

这称为通用协方差,在C#4.0中受支持。 您可以使用out关键字标记通用T参数:

 public interface ISomeInterface where T : SomeBaseClass 

但这有一个限制。 T参数只能作为接口中方法的返回类型出现。

Eric Lippert有一系列有关此主题的博客文章 ,我邀请您阅读。

是的,您可以使用inout关键字来利用协方差和逆变:

 public interface ISomeInterface where T : SomeBaseClass{ } 

要么:

 public interface ISomeInterface where T : SomeBaseClass{ } 

但请记住,使用中的关键字可以使用T作为参数,否则使用out可以使用T作为返回类型。

协方差:

当您可以从X转换为X时,类型是协变的。

逆变:

当您可以从X转换为X时,类型是逆变的。

– 其中S是子类,B是基类。


我在阅读C#4.0书时学到的一个有趣的例子是关于Stack的。

 class Stack{ int i; T[] array = new T[1000]; public void Push(T element){ array[i++] = element; } } class BaseClass{ } class SubClass : BaseClass{ } 

事实上它解释了在这种情况下,当Stack实现这个接口时,可以使用逆变:

 interface IPushable{ void Push(T element); } 

然后:

 IPushable stackB = new Stack(); IPushable stackS = stackB; stackS.Push(new SubClass()); 

虽然这种情况下的协方差,当Stack实现以下接口时:

 interface IPoppable{ T Pop(); } 

那么:

 IPoppable stackS = new Stack(); IPoppable stackB = stackB; BaseClass baseClass = stackB.Pop(); 

这非常有用,因为它允许没有任何问题的Upcast和downcast以及Compile-Time错误。

我不确定我是否正确理解了你的问题,但是你可能需要在检查一个类是否来自generics类时得到答案:

 public static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) { while (toCheck != null && toCheck != typeof(object)) { var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; if (generic == cur) return true; toCheck = toCheck.BaseType; } return false; } 

答案从你的第二个问题开始,因为它似乎显示了你想要实现的目标:

问:但是我如何检查它,如果我想对IList的对象实现是IList

你的推理似乎是因为字符串inheritance自object,你需要一个条件模式来检查通用情况。

 IList stringList = new List(); IList objectList = new List(); stringList is IList; //> true stringList is IList; //> false objectList is IList; //> false objectList is IList; //>true "someString" is object //> true 

因此,您只需检查Generic-Type构造的类型:

以及分别对IsGenericTypeIsGenericConstructedTypeIsGenericType布尔检查。

 objectList.GetType().GenericTypeArguments[0] is object //> true stringList.GetType().GenericTypeArguments[0] is object //> true 

警告:检查空案例; 如果支持语言等,则使用null coalescing和/或null条件运算符…为简洁和清晰起见,不在示例中


问:是否可以检查变量(inheritance)generics类型?

除了Darin和fuex的答案之外,还有其他指示:

  • 您可以使用Type的IEquality实现进行严格类型检查:

     bool condition = (someObject != null && someObject.GetType().Equals(typeof(ISomeInterface)) ); 
  • 您检查明确检查接口:

     var interfaces = someType.GetType().GetInterfaces(); //DotNet4.5: var interfaces = someType.GetType() // .GetTypeInfo().ImplementedInterfaces; bool condition = (interfaces != null && interfaces.ToList() .Contains(typeof(ISomeInterface)) == true); 

您几乎可以使用Type和TypeInfo构造任何条件检查