.net C#可选< TObject>作为返回类型?

w1jd8yoj  于 2022-11-19  发布在  .NET
关注(0)|答案(2)|浏览(187)

通常我有一个方法,如果出错了,我想返回错误,而不是返回null,我想在运行时更不容易出错,更容易使用。有没有什么已经在.Net中完成的,或者是一个nuget包?也许有一个带可选参数的构造函数或对象初始化器就足够了?
这可能是第一种方法,但每个新的Dto必须具有这些Error属性或从基类继承。

if (condition)
 {
     return new MyDto(null, error);
 }
 return new MyDto(someVariable, null);

所以我让这个类使用一个返回类型:

public class Optional<TObject> where TObject : class
{
   public Optional(TObject? value)
   {
       Value = value;
   }

   public Optional(String error)
   {
       Error = error;
   }

   public TObject? Value { get; }
   public String Error { get;} = String.Empty;
   public Boolean IsError => !String.IsNullOrEmpty(Error);
}

我在方法中返回它:

if (condition)
 {
     return new Optional(error);
 }

 return new Optional(new MyDto(someVariable));

然后像这样消耗它:

var result = await myService.GetSomethingAsync();
if(result.IsError)
{
   await DisplayAlert("error", result.Error, "Ok");
}
else
{
   await DoSomethingElse(result.Value);
}
ejk8hzay

ejk8hzay1#

通过创建一个小的类层次结构,可以确保Value属性仅在未发生错误时可用

public abstract class Result
{
    public virtual string Message => null;

    public static Error Error(string message) => new Error(message);
    public static Okay<T> Okay<T>(T value) where T : class => new Okay<T>(value);
}

public class Error : Result
{
    public Error(string errorMessage) => Message = errorMessage;

    override public string Message { get; }
}

public class Okay<T> : Result
    where T : class
{
    public Okay(T value) => Value = value;

    public T Value { get; }
}

用途

Result result = Result.Error("Something went wrong");
// OR
Result result = Result.Okay(new MyDto(someVariable));

if (result is Okay<MyDto> dtoResult) {
    Console.WriteLine(dtoResult.Value);
} else {
    Console.WriteLine(result.Message);
}

或者通过使用递归模式,我们可以直接将值检索到变量中

if (result is Okay<MyDto> { Value: var dto }) {
    Console.WriteLine(dto);
} else {
    Console.WriteLine(result.Message);
}

请注意,我已经在抽象基类Result中声明了Message属性,因此您不必强制转换为Error类型来获取消息。
我使用null作为错误消息的默认值,因为它允许我们写入

Console.Writeline(result.Message ?? "okay");
j9per5c4

j9per5c42#

你这推荐的OneOf看起来很有前途,我等下会亲自看看。
我对我的服务所做的是通过使用SvcResult类或继承类来标准化它们返回的结果。
示例:

public class SvcResult
{
    public List<Error> Errors { get; } // Error is a class of my own.  Add set; if deserialization is needed.
    public bool Success { get; } // Add set; if deserialization is needed.

    // Then parameterless constructor for a successful result.
    // Then parameterized constructor to receive errors for a failed result.
}

这是副作用服务调用的类,如果服务返回数据,我从上面派生创建DataSvcResult

public class DataSvcResult<TResult> : SvcResult
{
    public TResult Data { get; }

    // Add constructor that receives TResult for a successful object result.
    // Expose base class constructor that takes errors.
}

基本上我就是干这个的不过那个“我的一个”看起来很有趣

相关问题