无法隐式转换IEnumerable。

4
我有一个类,用于指示方法调用是否成功(带有值)或出现错误。
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);
}

我可以很好地进行隐式类型转换,除非 TValue 是一个 IEnumerable<T>

// Works
ValueOrError<int> x = 1;
// Fails
ValueOrError<IEnumerable<int>> y = Enumerable.Empty<int>();

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

然而,我可以通过“冗长的方式”创建该类型的结果

c# // 可行 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));
    }
}

隐式转换无法在接口之间进行。 - krimog
这个回答解决了你的问题吗?为什么不能从接口定义隐式转换运算符到类? - shingo
@krimog 谢谢。如果我在赋值之前隐式调用 ToArray(),那么它就可以工作了。如果您想将此作为答案添加,我会很乐意接受它。 - Peter Morris
1个回答

1
如果您查看C#规范关于用户定义的转换的内容:

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

使用隐式或显式操作符的先决条件之一是:

S₀和T₀都不是interface_type。

因此,如果您真的想使用隐式转换,您需要将接口引用转换为类引用(例如通过调用.ToArray())。
或者,您可以创建一个静态类来利用类型推断:
internal static class ValueOnError
{
    public static ValueOnError<TValue> FromValue<TValue>(TValue value)
        => ValueOnError<TValue>.FromValue(value);
}

那么,你可以直接写:
var y = ValueOnError.FromValue(Enumerable.Empty<int>());

也许可以加上从数组中推断而不是IEnumerable的部分,那样效果很好! - Peter Morris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接