Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展方法返回<;T>;而不是结果<;T>;_C#_Generics_Extension Methods_Func - Fatal编程技术网

C# 扩展方法返回<;T>;而不是结果<;T>;

C# 扩展方法返回<;T>;而不是结果<;T>;,c#,generics,extension-methods,func,C#,Generics,Extension Methods,Func,我正在学习Vladimir Khorikov的Result类,以及如何使用它来链接结果操作 他们的原创文章可以找到 可以找到他们的原始结果类代码 我编辑的结果类代码如下: public class Result { private bool _isSuccess; private string _errorMsg = ""; public bool IsSuccess() { return _isSuccess; } publi

我正在学习Vladimir Khorikov的
Result
类,以及如何使用它来链接结果操作

他们的原创文章可以找到

可以找到他们的原始
结果
类代码

我编辑的
结果
类代码如下:

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;
    }
}
下面是在
水果上操作的类:

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;
    }
}
我的问题是在下一个操作中尝试使用
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()));
水果=新水果(“苹果”);
Result-fruitResult=FruitOperator.AddAttribToFruit(水果,“大”,假)
.OnSuccess(水果操作员.AddAttribToFruit,水果,“红色”,真)
.OnFailure(lastFroothResult=>FroothOperator.MarkFroothAsBad(lastFroothResult.Value());
上面,
lastFruitResult
实际上是一个
水果
,而不是我预期的
结果


我的扩展方法签名是否有问题,或者我是否需要在使用它们时进行更改?

您在
OnFailure
中的签名有点错误。将其更改为
OnFailure(此结果为结果,动作为动作)

基本上,
操作
是接受多个参数的委托。与
Func
的区别在于
Action
不返回值

OnFailure(此结果为动作动作)
将允许消费者通过输入类型为
T
的动作。在您的例子中,
T
水果
,因为它实际上是在
AddAttribToFruit
中定义的,因为它返回
结果

将签名更改为:
OnFailure(此结果为结果,动作为动作)
它将允许消费者创建一个类型为
Result
的动作,在您的情况下为
Result

您的
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;
    }
失败时的公共静态结果(此结果,操作) { if(result.IsFailure()) { action(result);//注意result是result,action以result作为参数 } 返回结果; }

lastFruitResult
将是操作中定义的类型。

仔细查看
OnFailure中的
Action
(此结果,操作操作)
从第一眼开始。。。更改
操作操作
->
操作操作
OnFailure
@smoksnes嘿,它确实起作用了!你能加上这个作为回答吗?这样我就可以接受了?另外,您是否可以添加一个解释,说明更改失败时的签名如何影响我从成功时的签名?@Floating您不会从成功时的签名中获得最后的结果?这是从哪里来的?我只是想在这里补充最后的结论
Func
Action
确定使用
someIdentifer=>
时从被扩展对象获取的值(和数据类型)。
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()));
   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;
    }