我有第三方方法获得T的IEnumerable并对其进行评估。 我想在我的LINQ评估语句(select,where ...)中引入Option with exceptional values(或者),以获取需要输入方法的值。
对于每个T元素,我希望有一个方法可以返回转换后的元素或错误(将其保留为deferred execution)并且如果返回错误,则评估应该停在那里。 (从技术上讲,这可以通过抛出异常来实现,但这正是我试图避免使用Option)
我想知道这个概念是否可以用LINQ实现,或者更普遍地用C#实现?
如果无法实现,这会导致我在代码中使用抛出异常替换完全选项,因为使用带有选项的API可以为客户端显示相同的问题。
总之,这正是我想要实现的目标:
这可能是实现的一个可能的方法:
public Option<IEnumerable<T>,TError> Sequence<T,TError>(IEnumerable<Option<T,TError>> options)
其中:
应该使用延迟执行将IE的数量保留为
应该返回第一个错误
发现错误时应停止
**最终方法需要IE的数量,它将评估它(它可能是我无法访问的第三方方法) 而且我不想两次评估IEnumerable
答案 0 :(得分:0)
在尝试了一段时间来解决这个问题,并且感觉异常应该能够模仿monad之后,我发布了more conceptual version of this question。
谢谢,并基于马克的回答,这也证实了我对“与C#/ Java风格异常同构”的怀疑。
我能够创建以下实现:
public static class LinqEitherExtension
{
public static IEnumerable<T> UntilException<T,TException>(
this IEnumerable<Option<T,TException>> enumerable,
Action<TException> errorHandler
)
{
return enumerable
.TakeWhile(e =>
{
e.MatchNone(errorHandler);
return e.HasValue;
})
.SelectMany(e => e.ToEnumerable());
}
}
public class Program
{
static void Main(string[] args)
{
var numbers = new List<int> {1, 2, 3, 4, 5};
ThirdPartyFunction(numbers.Select(CheckNumbers).UntilException(Console.WriteLine));
//returns:
//1
//2
//3 is exceptional number.
}
public static Option<int,string> CheckNumbers(int number)
{
return number == 3
? Option.None<int, string>("3 is exceptional number.")
: number.Some<int, string>();
}
//Cannot be accessed/altered
public static void ThirdPartyFunction(IEnumerable<int> numbers)
{
foreach (var number in numbers) Console.WriteLine(number.ToString());
}
}
注意:如果在使用枚举之后,ThirdPartyFunction将继续执行副作用(如Console.WriteLine),那么在抛出异常和使用错误作为返回类型之间仍然存在差距:
对于我之后的事情将完成工作,但我想可能有更好的解决方案。