我已经实现了一个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。
此代码适用于类版本,但作为结构获取编译器错误。为什么呢?
答案 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;