简体   繁体   English

接口上的 C# 泛型隐式转换失败

[英]C# generic implicit cast on Interface failed

Why will the below not compile?为什么下面不能编译? What's special about the interface that causes the compiler to think it can't cast from Container<T> to T , when T is an interface?T是一个接口时,接口有什么特别之处会导致编译器认为它不能从Container<T>T I don't think its a covariant issue, as I'm not downcasting, but perhaps it is.我不认为这是一个协变问题,因为我并没有沮丧,但也许确实如此。 This is quite like Why C# compiler doesn't call implicit cast operator?这很像为什么 C# 编译器不调用隐式强制转换运算符? but I don't think it's quite the same.但我不认为这是完全一样的。

Product pIn =null;
Product pOut;
Container<Product> pContainer;

List<Product> pListIn = null;
List<Product> pListOut;
Container<List<Product>> pListContainer;

IList<Product> pIListIn = null;
IList<Product> pIListOut;
Container<IList<Product>> 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<T>
{
 private T value;

 private Container(T item) { value = item; }

 public static implicit operator Container<T>(T item)
 {
  return new Container<T>(item);
 }

 public static implicit operator T(Container<T> container)
 {
  return container.value;
 }
}

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

User defined conversions aren't allowed on interfaces at all.接口上根本不允许用户定义的转换。 It would potentially be ambiguous, because the type you're trying to convert from could implement the interface itself - at which point what would the cast mean?这可能是模棱两可的,因为您尝试从中转换的类型可以实现接口本身——此时转换意味着什么? A reference conversion like a normal cast, or an invocation of the user-defined conversion?像普通转换一样的引用转换,还是调用用户定义的转换?

From section 10.3.3 of the C# 4 spec:来自 C# 4 规范的第 10.3.3 节:

For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively.对于给定的源类型 S 和目标类型 T,如果 S 或 T 是可空类型,则让 S0 和 T0 指代它们的底层类型,否则 S0 和 T0 分别等于 S 和 T。 A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:仅当以下所有条件都为真时,才允许类或结构声明从源类型 S 到目标类型 T 的转换:

  • S0 and T0 are different types. S0 和 T0 是不同的类型。
  • Either S0 or T0 is the class or struct type in which the operator declaration takes place. S0 或 T0 是发生运算符声明的类或结构类型。
  • Neither S0 nor T0 is an interface-type. S0 和 T0 都不是接口类型。
  • Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.排除用户定义的转换,不存在从 S 到 T 或从 T 到 S 的转换。

and then later:然后:

However, it is possible to declare operators on generic types that, for particular type arguments, specify conversions that already exist as pre-defined conversions但是,可以在泛型类型上声明运算符,对于特定类型参数,可以将已存在的转换指定为预定义的转换
... ...
In cases where a pre-defined conversion exists between two types, any user-defined conversions between those types are ignored.在两种类型之间存在预定义转换的情况下,这些类型之间的任何用户定义转换都将被忽略。 Specifically:具体来说:

  • If a pre-defined implicit conversion (§6.1) exists from type S to type T, all user-defined conversions (implicit or explicit) from S to T are ignored.如果存在从类型 S 到类型 T 的预定义隐式转换(第 6.1 节),则忽略从 S 到 T 的所有用户定义的转换(隐式或显式)。
  • If a pre-defined explicit conversion (§6.2) exists from type S to type T, any user-defined explicit conversions from S to T are ignored.如果存在从类型 S 到类型 T 的预定义显式转换(第 6.2 节),则忽略任何用户定义的从 S 到 T 的显式转换。 Furthermore:此外:
    • If T is an interface type, user-defined implicit conversions from S to T are ignored.如果 T 是接口类型,则忽略从 S 到 T 的用户定义的隐式转换。
    • Otherwise, user-defined implicit conversions from S to T are still considered.否则,仍会考虑用户定义的从 S 到 T 的隐式转换。

Note the first nested bullet here.请注意此处的第一个嵌套项目符号。

(I can thoroughly recommend getting hold of the spec by the way. It's available online in various versions and formats , but the hardcopy annotated edition is also a goldmine of little nuggets from the team and others. I should confess a certain bias here, as I'm one of the annotators - but ignoring my stuff, all the other annotations are well worth reading!) (顺便说一下,我可以彻底推荐获取规范。它在网上有 各种版本和格式,但硬拷贝注释版也是团队和其他人的小金矿。我应该在这里承认一定的偏见,因为我是注释者之一 - 但忽略我的东西,所有其他注释都非常值得一读!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM