接口上的C#generics隐式强制转换失败

为什么以下不编译? 当T是接口时,导致编译器认为它无法从ContainerT的接口有什么特别之处? 我不认为这是一个协变问题,因为我不是在倾斜,但也许是。 这很像为什么C#编译器不调用隐式转换运算符? 但我不认为它是完全一样的。

 Product pIn =null; Product pOut; Container pContainer; List pListIn = null; List pListOut; Container<List> pListContainer; IList pIListIn = null; IList pIListOut; Container<IList> pIListContainer; pContainer = pIn; pOut = pContainer; // all good pListContainer = pListIn; pListOut = pListContainer; // all good too pIListContainer = pIListIn; // fails , cant do implicit cast for some reason pIListOut = pIListContainer; // and here too 

 class Container { private T value; private Container(T item) { value = item; } public static implicit operator Container(T item) { return new Container(item); } public static implicit operator T(Container container) { return container.value; } } 

 Cannot implicitly convert type 'Container<IList>' to 'IList'. An explicit conversion exists (are you missing a cast?) Cannot implicitly convert type 'IList' to 'Container<IList>'. An explicit conversion exists (are you missing a cast?) 

根本不允许在接口上进行用户定义的转换。 它可能是模棱两可的,因为你试图转换的类型可以实现接口本身 – 此时演员的意思是什么? 像普通强制转换一样的引用转换,还是用户定义转换的调用?

从C#4规范的第10.3.3节:

对于给定的源类型S和目标类型T,如果S或T是可空类型,则让S0和T0引用它们的基础类型,否则S0和T0分别等于S和T. 仅当满足以下所有条件时,才允许类或结构声明从源类型S到目标类型T的转换:

  • S0和T0是不同的类型。
  • S0或T0是发生运算符声明的类或结构类型。
  • S0和T0都不是接口类型。
  • 排除用户定义的转换,从S到T或从T到S不存在转换。

然后:

但是,可以在generics类型上声明运算符,对于特定类型参数,指定已作为预定义转换存在的转换

如果两种类型之间存在预定义的转换,则忽略这些类型之间的任何用户定义的转换。 特别:

  • 如果从类型S到类型T存在预定义的隐式转换(第6.1节),则忽略从S到T的所有用户定义的转换(隐式或显式)。
  • 如果从类型S到类型T存在预定义的显式转换(第6.2节),则忽略从S到T的任何用户定义的显式转换。 此外:
    • 如果T是接口类型,则忽略从S到T的用户定义的隐式转换。
    • 否则,仍会考虑用户定义的从S到T的隐式转换。

请注意这里的第一个嵌套项目符号。

(我可以完全建议顺便掌握规格。它可以在线获得各种版本和格式 ,但硬拷贝注释版本也是团队和其他人的小金块。我应该在这里承认一定的偏见,如同我是其中一位注释者 – 但忽略了我的东西,所有其他注释都值得一读!)