为什么我不能从受约束的泛型集合中推断接口?
Why can I not infer an interface from a constrained generic collection?
我有一段代码是这样工作的:
public IEnumerable<ICacheMember> Flubvert( IEnumerable<ICacheMember> members )
{
// do some stuff to members
return members;
}
但是我很困惑为什么我不能这样做:
public IEnumerable<T> ExecuteFlubversion<T>( IEnumerable<T> memberList ) where T: class,ICacheMember
{
return Flubvert( memberList );
}
对泛型的约束当然应该保证 memberList
是 ICacheMember
类型的 IEnumerable 吗?我真的需要将现有(但隐式)ICacheMember
对象的集合转换为 显式 ICacheMember
对象,然后再将它们转换回来吗?我可以理解,鉴于 Flubvert
的方法签名,我可能需要将它们转换回来,但我不明白为什么我必须在方法调用中转换它们。这就是我在工作代码中所做的,但它似乎完全不符合泛型的一般优雅行为,所以我想我一定是误解了它应该如何运作。
首先 IEnumerable<out T>
(和其他泛型类型)的协变仅在 T
是引用类型时有效,因此您需要:
public IEnumerable<ICacheMember> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T: class, ICacheMember // NOTE 'class'
{
var flub = Flubvert(memberList); // can you call with 'memberList'?
return flub; // can you return that type?
// depending on what 'Flubvert' does, maybe return 'IEnumerable<T>'
// and say:
// return (IEnumerable<T>)flub;
}
另请注意,我更改了 return 值。 C# 编译器无法保证来自非泛型 Flubvert
方法的 returned 对象比 IEnumerable<ICacheMember>
.
更具体
假设您有:
interface ICacheMemberSub : ICacheMember
{
...
}
你这样调用你的函数:
ExecuteFlubversion<ICacheMemberSub>(cacheMember);
此函数将尝试 return 类型为 IEnumerable<ICacheMember>
的对象,而该对象不一定可转换为 IEnumerable<ICacheMemberSub>
,因此会出现错误。
冒着不能直接回答问题的风险,能否将Flubvert的签名改成通用的?如果你使 Flubvert 通用,其余的方法代码将保持不变,你仍然可以假设成员将是 ICacheMember 的实现者。
public IEnumerable<T> Flubvert<T>(IEnumerable<T> members)
where T : class, ICacheMember
{
// do some stuff to members
return members;
}
public IEnumerable<T> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T : class,ICacheMember
{
return Flubvert(memberList);
}
我有一段代码是这样工作的:
public IEnumerable<ICacheMember> Flubvert( IEnumerable<ICacheMember> members )
{
// do some stuff to members
return members;
}
但是我很困惑为什么我不能这样做:
public IEnumerable<T> ExecuteFlubversion<T>( IEnumerable<T> memberList ) where T: class,ICacheMember
{
return Flubvert( memberList );
}
对泛型的约束当然应该保证 memberList
是 ICacheMember
类型的 IEnumerable 吗?我真的需要将现有(但隐式)ICacheMember
对象的集合转换为 显式 ICacheMember
对象,然后再将它们转换回来吗?我可以理解,鉴于 Flubvert
的方法签名,我可能需要将它们转换回来,但我不明白为什么我必须在方法调用中转换它们。这就是我在工作代码中所做的,但它似乎完全不符合泛型的一般优雅行为,所以我想我一定是误解了它应该如何运作。
首先 IEnumerable<out T>
(和其他泛型类型)的协变仅在 T
是引用类型时有效,因此您需要:
public IEnumerable<ICacheMember> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T: class, ICacheMember // NOTE 'class'
{
var flub = Flubvert(memberList); // can you call with 'memberList'?
return flub; // can you return that type?
// depending on what 'Flubvert' does, maybe return 'IEnumerable<T>'
// and say:
// return (IEnumerable<T>)flub;
}
另请注意,我更改了 return 值。 C# 编译器无法保证来自非泛型 Flubvert
方法的 returned 对象比 IEnumerable<ICacheMember>
.
假设您有:
interface ICacheMemberSub : ICacheMember
{
...
}
你这样调用你的函数:
ExecuteFlubversion<ICacheMemberSub>(cacheMember);
此函数将尝试 return 类型为 IEnumerable<ICacheMember>
的对象,而该对象不一定可转换为 IEnumerable<ICacheMemberSub>
,因此会出现错误。
冒着不能直接回答问题的风险,能否将Flubvert的签名改成通用的?如果你使 Flubvert 通用,其余的方法代码将保持不变,你仍然可以假设成员将是 ICacheMember 的实现者。
public IEnumerable<T> Flubvert<T>(IEnumerable<T> members)
where T : class, ICacheMember
{
// do some stuff to members
return members;
}
public IEnumerable<T> ExecuteFlubversion<T>(IEnumerable<T> memberList)
where T : class,ICacheMember
{
return Flubvert(memberList);
}