[英]Unable to return IEnumerable<TEnum> in place of IEnumerable<T>
我写了这个EnumHelper方法
public static IEnumerable<T> AsEnumerable<TEnum, T>(Func<TEnum, T> projection = null) where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new InvalidOperationException("Type parameter TEnum must be an enum");
if (projection == null)
return Enum.GetValues(typeof (TEnum)).OfType<TEnum>();
return Enum.GetValues(typeof (TEnum)).OfType<TEnum>().Select(projection);
}
我在第一次返回时遇到编译时错误。 返回IEnumerable<TEnum>
错误46无法将System.Collections.Generic.IEnumerable<TEnum>
类型隐式转换为System.Collections.Generic.IEnumerable<T>
我对T
没有任何限制,所以T
比TEnum
更通用。 在IEnumerable<out T>
T
是可变的,为什么我仍然得到错误?
协方差仅适用于两种类型之间存在多态关系的情况。 在您的情况下, TEnum
和T
TEnum
于相关,因此协方差不适用。
您可以通过将枚举成员直接转换为目标类型来轻松解决此问题:
if (projection == null)
return Enum.GetValues(typeof(TEnum)).OfType<T>();
编辑 :我建议删除projection
参数,并更简单地定义您的方法:
public static IEnumerable<TEnum> AsEnumerable<TEnum>() where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new InvalidOperationException("Type parameter TEnum must be an enum");
return Enum.GetValues(typeof(TEnum)).OfType<TEnum>();
}
如果确实需要执行投影,可以对返回的序列使用标准的LINQ Select
操作:
var optionsA = AsEnumerable<RegexOptions>();
var optionsB = AsEnumerable<RegexOptions>().Select(o => o.ToString());
这将为您提供与代码几乎相同的简洁性,但省去了维护可选参数的麻烦。
编辑2 :如果你真的想为投影定义一个重载,我建议实现其中的所有逻辑,然后使用无参数版本中的标识函数调用它:
public static IEnumerable<TEnum> AsEnumerable<TEnum>() where TEnum : struct
{
return AsEnumerable<TEnum, TEnum>(e => e);
}
public static IEnumerable<TResult> AsEnumerable<TEnum, TResult>(
Func<TEnum, TResult> projection) where TEnum : struct
{
if (!typeof(TEnum).IsEnum)
throw new InvalidOperationException("Type parameter TEnum must be an enum");
return Enum.GetValues(typeof(TEnum)).OfType<TEnum>().Select(projection);
}
示例电话:
var optionsA = AsEnumerable<RegexOptions>();
var optionsB = AsEnumerable<RegexOptions, string>(o => o.ToString());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.