You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何IReadOnlyCollection无法触发Either类型的隐式转换?

问题分析:隐式转换结构体Either的编译异常问题

问题场景

定义了带隐式转换的只读结构体Either<TLeft, TRight>,以及接收Either<IReadOnlyCollection<int>, int>的记录类型SomeType。测试时,直接传入IReadOnlyCollection<int>类型的变量编译失败,但传入int[]类型的变量却能正常编译——明明前者和Either的Left类型完全匹配,请问原因是什么?

复现代码

public readonly struct Either<TLeft, TRight>
{
    public TLeft? Left { get; } = default;
    public TRight? Right { get; } = default;

    public static implicit operator Either<TLeft, TRight>(TLeft left) => new(left);
    public static implicit operator Either<TLeft, TRight>(TRight right) => new(right);

    private Either(TLeft left) => Left = left;
    private Either(TRight right) => Right = right;
}

public record SomeType(Either<IReadOnlyCollection<int>, int> Something);

public class Class1
{
    public void Run()
    {
        IReadOnlyCollection<int> test1 = new[] { 1, 2 };
        int[] test2 = new[] { 1, 2 };

        var d1 = new SomeType(test1);  // 编译失败
        var d2 = new SomeType(test2);  // 编译正常
    }
}

编译错误信息

参数类型“System.Collections.Generic.IReadOnlyCollection”无法分配给参数类型“EitherExperiments.Either<System.Collections.Generic.IReadOnlyCollection, int>”

原因解析

这是C#隐式转换解析规则导致的:

  • 对于test2(int[]类型),编译器可完成链式隐式转换:先将int[]转换为IReadOnlyCollection<int>(数组实现了该接口,属于引用转换),再调用Either<IReadOnlyCollection<int>, int>的左值隐式转换操作符,最终得到目标类型,整个路径唯一且明确。
  • 对于test1(IReadOnlyCollection<int>类型),问题出在泛型隐式转换的类型推断限制:
    Either<TLeft, TRight>的隐式转换是泛型静态方法,编译器需要先确定TLeft和TRight的具体类型才能匹配操作符。当传入IReadOnlyCollection<int>时,编译器无法唯一确定目标Either的类型参数——它没办法排除该值会不会被匹配到右侧的TRight=int转换(尽管逻辑上不可能,但编译器不会做语义层面的判断),因此无法找到符合要求的隐式转换路径。

解决方法

要让test1的调用正常编译,可显式指定转换类型,帮编译器明确目标类型:

var d1 = new SomeType((Either<IReadOnlyCollection<int>, int>)test1);

内容的提问来源于stack exchange,提问作者mnj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:46:30