扩展方法返回 <T> 而不是结果 <T>
Extension Method Returning <T> Instead of Result<T>
我正在研究 Vladimir Khorikov 的 Result
class 以及如何使用它来链接结果操作。
可以找到他们的原创文章here。
他们原来的 Result
class 代码可以找到 here.
我编辑的Result
class代码如下:
public class Result
{
private bool _isSuccess;
private string _errorMsg = "";
public bool IsSuccess()
{
return _isSuccess;
}
public bool IsFailure()
{
return !_isSuccess;
}
public string ErrorMsg()
{
return _errorMsg;
}
public Result(bool isSuccess, string errorMsg)
{
bool errorMsgIsEmpty = string.IsNullOrEmpty(errorMsg);
if (isSuccess && !errorMsgIsEmpty)
{
throw new Exception("cannot have error message for successful result");
}
else if (!isSuccess && errorMsgIsEmpty)
{
throw new Exception("must have error message for unsuccessful result");
}
_isSuccess = isSuccess;
if (!errorMsgIsEmpty)
{
_errorMsg = errorMsg;
}
}
public static Result Fail(string errorMsg)
{
return new Result(false, errorMsg);
}
public static Result<T> Fail<T>(string errorMsg)
{
return new Result<T>(default(T), false, errorMsg);
}
public static Result OK()
{
return new Result(true, "");
}
public static Result<T> OK<T>(T value)
{
return new Result<T>(value, true, "");
}
public static Result Combine(params Result[] results)
{
foreach (Result result in results)
{
if (result.IsFailure())
{
return result;
}
}
return OK();
}
}
public class Result<T> : Result
{
private T _value;
public T Value()
{
return _value;
}
public Result(T value, bool isSuccess, string errorMsg) : base(isSuccess, errorMsg)
{
_value = value;
}
}
我正在进行以下测试 class:
public class Fruit
{
private string _name = "";
private StringBuilder _attribs;
public bool isBad;
public Fruit(string name)
{
_name = name;
_attribs = new StringBuilder();
}
public string Name()
{
return _name;
}
public string Attribs()
{
string attribs = _attribs.ToString();
if (attribs.Length > 0)
{
return attribs.Remove(attribs.Length - 2);
}
return attribs;
}
public void AddAttrib(string attrib)
{
_attribs.Append(attrib + ", ");
}
}
下面是在Fruit
上运行的class:
public class FruitOperator
{
public static Result<Fruit> AddAttribToFruit(Fruit fruit, string attrib, bool fail)
{
if (fail)
{
return Result.Fail<Fruit>("failed");
}
fruit.AddAttrib(attrib);
return Result.OK<Fruit>(fruit);
}
public static void MarkFruitAsBad(Fruit fruit)
{
fruit.isBad = true;
}
}
我创建了以下 Result
扩展方法来匹配 AddAttribToFruit
和 MarkFruitAsBad
的函数签名:
public static class ResultExtensions
{
public static Result<T> OnSuccess<T>(this Result<T> result, Func<T, string, bool, Result<T>> func, T val, string str, bool flag)
{
if (result.IsFailure())
{
return result;
}
return func(val, str, flag);
}
public static Result<T> OnFailure<T>(this Result<T> result, Action<T> action)
{
if (result.IsFailure())
{
action(result.Value());
}
return result;
}
}
我的问题是当我尝试在下一个操作中使用 OnSuccess
的结果时:
Fruit fruit = new Fruit("apple");
Result<Fruit> fruitResult = FruitOperator.AddAttribToFruit(fruit, "big", false)
.OnSuccess(FruitOperator.AddAttribToFruit, fruit, "red", true)
.OnFailure(lastFruitResult => FruitOperator.MarkFruitAsBad(lastFruitResult.Value()));
以上,lastFruitResult
实际上是Fruit
而不是我预期的Result<Fruit>
。
我的扩展方法签名是否有问题,或者我需要根据我的使用方式进行更改?
您在 OnFailure
中的签名有点错误。将其更改为 OnFailure<T>(this Result<T> result, Action<Result<T>> action)
.
基本上,Action
是一个带有多个参数的委托。与 Func
的区别在于 Action
不是 return 值。
OnFailure<T>(this Result<T> result, Action<T> action)
将让消费者传递类型为 T
的操作作为输入。在你的情况下 T
是 Fruit
因为它实际上是在 AddAttribToFruit
中定义的,因为它 returns Result<Fruit>
.
通过将签名更改为:
OnFailure<T>(this Result<T> result, Action<Result<T>> action)
它将让消费者创建类型为 Result<T>
的操作,在您的情况下为 Result<Fruit>
.
您的 OnFailure
可能看起来像这样:
public static Result<T> OnFailure<T>(this Result<T> result, Action<Result<T>> action)
{
if (result.IsFailure())
{
action(result); // Note that result is Result<T> and action takes Result<T> as parameter
}
return result;
}
lastFruitResult
将是 Action<here>.
中定义的类型
我正在研究 Vladimir Khorikov 的 Result
class 以及如何使用它来链接结果操作。
可以找到他们的原创文章here。
他们原来的 Result
class 代码可以找到 here.
我编辑的Result
class代码如下:
public class Result
{
private bool _isSuccess;
private string _errorMsg = "";
public bool IsSuccess()
{
return _isSuccess;
}
public bool IsFailure()
{
return !_isSuccess;
}
public string ErrorMsg()
{
return _errorMsg;
}
public Result(bool isSuccess, string errorMsg)
{
bool errorMsgIsEmpty = string.IsNullOrEmpty(errorMsg);
if (isSuccess && !errorMsgIsEmpty)
{
throw new Exception("cannot have error message for successful result");
}
else if (!isSuccess && errorMsgIsEmpty)
{
throw new Exception("must have error message for unsuccessful result");
}
_isSuccess = isSuccess;
if (!errorMsgIsEmpty)
{
_errorMsg = errorMsg;
}
}
public static Result Fail(string errorMsg)
{
return new Result(false, errorMsg);
}
public static Result<T> Fail<T>(string errorMsg)
{
return new Result<T>(default(T), false, errorMsg);
}
public static Result OK()
{
return new Result(true, "");
}
public static Result<T> OK<T>(T value)
{
return new Result<T>(value, true, "");
}
public static Result Combine(params Result[] results)
{
foreach (Result result in results)
{
if (result.IsFailure())
{
return result;
}
}
return OK();
}
}
public class Result<T> : Result
{
private T _value;
public T Value()
{
return _value;
}
public Result(T value, bool isSuccess, string errorMsg) : base(isSuccess, errorMsg)
{
_value = value;
}
}
我正在进行以下测试 class:
public class Fruit
{
private string _name = "";
private StringBuilder _attribs;
public bool isBad;
public Fruit(string name)
{
_name = name;
_attribs = new StringBuilder();
}
public string Name()
{
return _name;
}
public string Attribs()
{
string attribs = _attribs.ToString();
if (attribs.Length > 0)
{
return attribs.Remove(attribs.Length - 2);
}
return attribs;
}
public void AddAttrib(string attrib)
{
_attribs.Append(attrib + ", ");
}
}
下面是在Fruit
上运行的class:
public class FruitOperator
{
public static Result<Fruit> AddAttribToFruit(Fruit fruit, string attrib, bool fail)
{
if (fail)
{
return Result.Fail<Fruit>("failed");
}
fruit.AddAttrib(attrib);
return Result.OK<Fruit>(fruit);
}
public static void MarkFruitAsBad(Fruit fruit)
{
fruit.isBad = true;
}
}
我创建了以下 Result
扩展方法来匹配 AddAttribToFruit
和 MarkFruitAsBad
的函数签名:
public static class ResultExtensions
{
public static Result<T> OnSuccess<T>(this Result<T> result, Func<T, string, bool, Result<T>> func, T val, string str, bool flag)
{
if (result.IsFailure())
{
return result;
}
return func(val, str, flag);
}
public static Result<T> OnFailure<T>(this Result<T> result, Action<T> action)
{
if (result.IsFailure())
{
action(result.Value());
}
return result;
}
}
我的问题是当我尝试在下一个操作中使用 OnSuccess
的结果时:
Fruit fruit = new Fruit("apple");
Result<Fruit> fruitResult = FruitOperator.AddAttribToFruit(fruit, "big", false)
.OnSuccess(FruitOperator.AddAttribToFruit, fruit, "red", true)
.OnFailure(lastFruitResult => FruitOperator.MarkFruitAsBad(lastFruitResult.Value()));
以上,lastFruitResult
实际上是Fruit
而不是我预期的Result<Fruit>
。
我的扩展方法签名是否有问题,或者我需要根据我的使用方式进行更改?
您在 OnFailure
中的签名有点错误。将其更改为 OnFailure<T>(this Result<T> result, Action<Result<T>> action)
.
基本上,Action
是一个带有多个参数的委托。与 Func
的区别在于 Action
不是 return 值。
OnFailure<T>(this Result<T> result, Action<T> action)
将让消费者传递类型为 T
的操作作为输入。在你的情况下 T
是 Fruit
因为它实际上是在 AddAttribToFruit
中定义的,因为它 returns Result<Fruit>
.
通过将签名更改为:
OnFailure<T>(this Result<T> result, Action<Result<T>> action)
它将让消费者创建类型为 Result<T>
的操作,在您的情况下为 Result<Fruit>
.
您的 OnFailure
可能看起来像这样:
public static Result<T> OnFailure<T>(this Result<T> result, Action<Result<T>> action)
{
if (result.IsFailure())
{
action(result); // Note that result is Result<T> and action takes Result<T> as parameter
}
return result;
}
lastFruitResult
将是 Action<here>.