使用LINQ

时间:2015-12-16 21:43:06

标签: c# linq class struct ienumerable

我已经实现了一个Maybe<T>类,它在C#的启发下实现了由Mark Seemann启发的IEnumerable,并且效果很好。我有一套辅助扩展方法,可以使常见的操作也许友好,而且它们也都很好用。我有想法将Maybe<T>从一个类更改为一个结构,以防止它可以为空,它似乎可以解决一个问题:

var inputs = new Maybe<string>[] { /* from somewhere */ };

// This line works with class Maybe and struct Maybe
var results1 = inputs.SelectMany(x => ParseMaybe.ToInt32(x));

// This line works with class Maybe but with struct Maybe it yields a compiler error: 
// Error CS0407 'Maybe<int> ParseMaybe.ToInt32(string)' has the wrong return type
var results2 = inputs.SelectMany(ParseMaybe.ToInt32);

注意:因为Maybe在这里实现IEnumerable,我使用的是SelectMany而不是Select。

此代码适用于类版本,但作为结构获取编译器错误。为什么呢?

1 个答案:

答案 0 :(得分:3)

这是因为结构类型参数是不变的。尽管Func<A, B>在其返回类型中是协变的,但这仅适用于B是引用类型的情况。这意味着,即使Func<string, Maybe<int>>实施Func<string, IEnumerable<int>>,您也无法将Maybe<T>分配给IEnumerable<T>,例如

Func<string, Maybe<int>> f = ParseMaybe.ToInt32;
Func<string, IEnumerable<int>> g = f; //won't compile

相反,以下将编译,因为int[]是引用类型:

Func<string, int[]> f = ???
Func<string, IEnumerable<int>> g = f;