在三元条件隐式转换问题 [英] Implicit conversion issue in a ternary condition

查看:113
本文介绍了在三元条件隐式转换问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  <一href=\"http://stackoverflow.com/questions/2215745/conditional-operator-cannot-cast-implicitly\">Conditional经营者不能隐式转换?结果
  为什么空需要在这里投了明确的类型?

我有一个搜索,并没有发现,为什么会发生以下情况一个很好的解释。结果
我有一个有共同的接口两个阶级,我曾尝试初始化使用三元操作如下,接口类型的实例,但这一失败,有条件的前pression的错误类型编译无法确定,因为有

I've had a search and haven't found a good explanation for why the following occurs.
I have two classes which have an interface in common and I have tried initializing an instance of this interface type using the ternary operator as below but this fails to compile with the error "Type of conditional expression cannot be determined because there is no implicit conversion between 'xxx.Class1' and 'xxx.Class2':

public ConsoleLogger : ILogger  { .... }

public SuppressLogger : ILogger  { .... }

static void Main(string[] args)
{
   .....
   // The following creates the compile error
   ILogger logger = suppressLogging ? new SuppressLogger() : new ConsoleLogger();
}

这工作,如果我明确先拿conditioin到我的界面:

This works if I explicitly cast the first conditioin to my interface:

   ILogger logger = suppressLogging ? ((ILogger)new SuppressLogger()) : new ConsoleLogger();

和很明显,我总是可以做到这一点:

and obviously I can always do this:

   ILogger logger;
   if (suppressLogging)
   {
       logger = new SuppressLogger();
   }
   else
   {
       logger = new ConsoleLogger();
   }

的替代品是不错,但作为,在我看来,这两个类的类型是ILogger我不能完全得到我的身边,为什么第一个选项失败,隐式转换错误的头,我真的不希望做一个转换(隐性或显性)。我敢肯定,这可能是一个静态的语言编写的问题,但我想明白是怎么回事。

The alternatives are fine but I can't quite get my head around why the first option fails with the implicit conversion error as, in my view, both classes are of type ILogger and I am not really looking to do a conversion (implicit or explicit). I'm sure this is probably a static language compilation issue but I would like to understand what is going on.

推荐答案

这是C#的两个特点融合的结果。

This is a consequence of the confluence of two characteristics of C#.

首先,C#从来没有魔法了一种适合你。如果C#必须确定从给定的类型,以最好的类型,它总是挑选你给它的类型之一。它从来不说没有你给我的最好的类型的类型,因为选择,你给我的都是坏的,我会挑你没有给我可以选择一些随机的事情。

The first is that C# never "magics up" a type for you. If C# must determine a "best" type from a given set of types, it always picks one of the types you gave it. It never says "none of the types you gave me are the best type; since the choices you gave me are all bad, I'm going to pick some random thing that you did not give me to choose from."

二是从的之外的C#里面的原因的到的。我们不说哦,我知道你想的条件运算结果分配给ILogger,让我确保这两个分支的工作。与此相反的情况:让我确定由两个分支返回的最好的类型,并验证的最佳类型转换为目标类型C#说:

The second is that C# reasons from inside to outside. We do not say "Oh, I see you are trying to assign the conditional operator result to an ILogger; let me make sure that both branches work." The opposite happens: C# says "let me determine the best type returned by both branches, and verify that the best type is convertible to the target type."

第二个规则是明智的,因为的目标类型可能是什么,我们正试图确定。的当你说 D D = B? C:一个; 很显然目标类型是什么。但是,假设你是不是调用 M(B C:A)?有可能是M的一百个不同的重载每一个不同类型的形式参数!我们必须确定参数的类型是什么,然后丢弃,因为参数类型与正式参数类型兼容这是不适用M的重载;我们不走另一条路。

The second rule is sensible because the target type might be what we are trying to determine. When you say D d = b ? c : a; it is clear what the target type is. But suppose you were instead calling M(b?c:a)? There might be a hundred different overloads of M each with a different type for the formal parameter! We have to determine what the type of the argument is, and then discard overloads of M which are not applicable because the argument type is not compatible with the formal parameter type; we don't go the other way.

考虑一下,如果我们去其他的方式会发生什么:

Consider what would happen if we went the other way:

M1( b1 ? M2( b3 ? M4( ) : M5 ( ) ) : M6 ( b7 ? M8() : M9() ) );

假设有一个重载每个M1,M2和M6百。你是做什么?你说好,如果这是M1(美孚),则M2(...)和M6(...)都必须是转换为富。是什么人?让我们来了解一下。什么是M2的过载?有上百种可能性。让我们来看看他们每个人从M4和M5的返回类型转换... OK,我们已经尝试了所有这些,所以我们找到问题的M2。现在来谈谈M6?如果最好的M2,我们发现有什么不与最佳M6兼容?我们应该走回头路,继续重新尝试所有的100×100的可能性,直到我们找到一个兼容的对?这个问题只会越来越糟。

Suppose there are a hundred overloads each of M1, M2 and M6. What do you do? Do you say, OK, if this is M1(Foo) then M2(...) and M6(...) must be both convertible to Foo. Are they? Let's find out. What's the overload of M2? There are a hundred possibilities. Let's see if each of them is convertible from the return type of M4 and M5... OK, we've tried all those, so we've found an M2 that works. Now what about M6? What if the "best" M2 we find is not compatible with the "best" M6? Should we backtrack and keep on re-trying all 100 x 100 possibilities until we find a compatible pair? The problem just gets worse and worse.

我们的的原因,以这种方式为lambda表达式和lambda表达式涉及的结果超载分辨率至少为NP-HARD在C#。这是不好的就在那里;我们宁可不要让编译器解决增加更多的NP难问题。

We do reason in this manner for lambdas and as a result overload resolution involving lambdas is at least NP-HARD in C#. That is bad right there; we would rather not add more NP-HARD problems for the compiler to solve.

您可以看到在语言在其他地方行动的第一条规则也是如此。例如,如果你说: ILogger [] =伐木工人新[] {consoleLogger,SUP pressLogger}; 你会得到一个类似的错误;推断出数组元素类型必须的最佳类型给出的类型化前pressions的的。如果没有最好的类型可以从他们的决定,我们不会试图找到一种你没有给我们。

You can see the first rule in action in other place in the language as well. For example, if you said: ILogger[] loggers = new[] { consoleLogger, suppressLogger }; you'd get a similar error; the inferred array element type must be the best type of the typed expressions given. If no best type can be determined from them, we don't try to find a type you did not give us.

同样的事情会在类型推断。如果你说:

Same thing goes in type inference. If you said:

void M<T>(T t1, T t2) { ... }
...
M(consoleLogger, suppressLogger);

则T将不会被推断为ILogger;这将是一个错误。 T被推断为跻身提供的参数类型最好的类型,并没有在他们中间没有最好的类型。

Then T would not be inferred to be ILogger; this would be an error. T is inferred to be the best type amongst the supplied argument types, and there is no best type amongst them.

有关这个设计决定如何影响条件运算符的行为的详细信息,请参阅我一系列关于该主题的文章

For more details on how this design decision influences the behaviour of the conditional operator, see my series of articles on that topic.

如果您有兴趣,为什么重载的作品从外到内是NP-HARD,请参阅this文章

If you are interested in why overload resolution that works "from outside to inside" is NP-HARD, see this article.

这篇关于在三元条件隐式转换问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆