无法隐式转换 IEnumerable

Cannot implicitly cast IEnumerable

我有一个 class 指示对方法的调用是成功(有值)还是有错误。

internal sealed class ValueOrError<TValue>
{
    public bool IsError => _error is not null;
    public bool IsSuccess => !IsError;

    private TValue? _value;
    private Error? _error;

    private ValueOrError() { }

    public TValue? Value =>
        _error is null
        ? _value
        : throw new InvalidOperationException("Is an error type");

    public Error Error => _error ?? throw new InvalidOperationException("Not an error type");

    public static ValueOrError<TValue> FromValue(TValue? result) =>
        new ValueOrError<TValue> { _value = result };

    public static ValueOrError<TValue> FromError(Error error) =>
        new ValueOrError<TValue> { _error = error ?? throw new ArgumentNullException(nameof(error)) };

    public static implicit operator ValueOrError<TValue>(TValue value) => ValueOrError<TValue>.FromValue(value);
    public static implicit operator ValueOrError<TValue>(Error error) => ValueOrError<TValue>.FromError(error);
}

除非 TValueIEnumerable<T>.

,否则我可以隐式转换
// Works
ValueOrError<int> x = 1;
// Fails
ValueOrError<IEnumerable<int>> y = Enumerable.Empty<int>();

无法将类型 'System.Collections.Generic.IEnumerable' 隐式转换为 'AppLayer.ValueOrError'

但是,我可以创建“长途”类型的结果

c# // Works ValueOrError<IEnumerable<int>>.FromValue(Enumerable.Empty<int>());

如果有用,Error的来源是

public class Error
{
    public string Message { get; }

    [JsonConstructor]
    public Error(string message)
    {
        Message = message ?? throw new ArgumentNullException(nameof(message));
    }
}

如果您查看有关 User-defined 转换的 C# 规范:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions#105-user-defined-conversions

使用隐式或显式运算符的先决条件之一是

Neither S₀ nor T₀ is an interface_type.

因此,如果您真的想使用隐式转换,则必须将接口引用转换为 class 引用(例如通过调用 .ToArray())。

或者您可以创建静态 class 以利用类型推断:

internal static class ValueOnError
{
    public static ValueOnError<TValue> FromValue<TValue>(TValue value)
        => ValueOnError<TValue>.FromValue(value);
}

那你就可以写

var y = ValueOnError.FromValue(Enumerable.Empty<int>());