【发布时间】:2017-10-14 19:50:17
【问题描述】:
假设我有两个类,Foo 和 Bar。
public class Foo<TFirst, TSecond, TThird, T>
where TFirst : IReadOnlyList<T>
where TThird : IEnumerable<T>
{
}
public class Bar<TFirst, TSecond, TThird, T>
where TFirst : IReadOnlyList<T>
{
}
现在我想比较它们的泛型类型。我正在使用相等比较器对类型数组进行操作。比如相交、相减等。
我不想比较Foo 和Bar,但我想比较它们的通用参数。
例如,如果两个类型参数具有相同的约束,则它们应该被视为相等。如果他们没有约束,他们也应该被认为是平等的。
在上面的例子中,Foo 的 TFirst 应该被认为等于 Bar 的 TFirst。以及TSecond,因为它们没有约束。 TThrids 不相等,因为它们没有相同的约束。
所以现在我有 Foo 和 Bar 类型。我想分析它们的类型参数并将它们相互比较。
var fooType = typeof(Foo<,,,>);
var barType = typeof(Bar<,,,>);
var fooArgs = fooType.GetGenericArguments();
var barArgs = barType.GetGenericArguments();
var commonArgs = fooArgs.Intersect(barArgs, new GenericArgumentEqualityComparer()).ToArray();
var unknownBarArgs = barArgs.Except(commonArgs, new GenericArgumentEqualityComparer()).ToArray();
无论我使用IsAssignableFrom 还是==,遵循平等比较器总是返回false。这样做的正确方法是什么?
public class GenericArgumentEqualityComparer : IEqualityComparer<Type>
{
public bool Equals(Type x, Type y)
{
if (x == null || y == null) return false;
var xcons = x.GetGenericParameterConstraints();
var ycons = y.GetGenericParameterConstraints();
if(xcons.Length != ycons.Length) return false;
foreach (var cons in xcons)
{
if (ycons.All(cons2 => !cons.IsAssignableFrom(cons2)))
return false;
}
return true;
}
public int GetHashCode(Type obj)
{
// code runs on T4 for code generation. performance doesn't matter.
return 0;
}
}
【问题讨论】:
-
您的代码不会编译,因为 T 没有定义。你是说TSecond
-
@BRAHIMKamel 你可以添加另一个类型参数
T。对不起,我错过了。它们只是示例 -
@BRAHIMKamel 的重点是,因为
T没有约束,所以无论取自 Foo 还是 Bar 都应该被认为是相等的。如果定义了约束,它们必须相同才能被视为相等。
标签: c# generics reflection type-inference