Почему я получаю ошибку компиляции, бросая запечатанный класс к интерфейсу, который это могло бы осуществить?

Следующий код дает ошибке компилятора CS0030 (собранный с компилятором C# ПРОТИВ 2012), хотя бросок мог бы добиться успеха во времени выполнения. Удаление , запечатанный ключевое слово, использование как , бросок или добавление промежуточного броска, чтобы объект совершают ошибку, уходят.

  public interface IFunny { }

  public sealed class Funny : IFunny
  {
    public IFunny Cast ()
    {
     //error CS0030: Cannot convert type Funny' to 'IFunny'.
      return (IFunny) this;
    }
  }

Это кажется мне, компилятор использует эвристическое для запечатанных классов только, которое слишком строго в случае универсальных интерфейсных внедрений.

Это действительно слишком строго (в смысле ошибки) или является там серьезным основанием для этой ошибки?

Update: A clarification to my question: The compiler cannot determine whether there is a relationship between TOther and T at compile time. The cast would succeed, at runtime, if TOther is the same or a base class of T, and it would fail in all other cases. This is true no matter whether Funny is sealed or not.

Компилятор C# обычно не предотвращает броски, которые могли бы добиться успеха во времени выполнения. (Например, я могу бросить случай статического типа объект , чтобы IComparable , вызвав исключение на этапе выполнения, если случай действительно не осуществляет тот интерфейс.), Почему это делает так в этом , запечатанный случай?

9
nl ja de
С тех пор нет никаких отношений между T и TOther it' s невозможный, который знает компилятор, как бросить. Но если бы вы вместо этого возвращаетесь это как IFunny , который работал бы, поскольку возвращаемое значение броска может также быть пустым.
добавлено автор Marius Bancila, источник
@w0lf, Ворчун, Мариус - то же самое обратились бы если класс isn' t отмеченный запечатанный , все же , что собирает.
добавлено автор Rawling, источник
I' d думают, что компилятор отказывается от этого, потому что T и TOther не всегда совместимы. ((IFunny <�объект>) новый Забавный <�Последовательность> ()) будет, вероятно, работать...
добавлено автор TGlatzer, источник
есть ли отношения между T и TOther ? Как компилятор мог знать это?
добавлено автор GolfWolf, источник
Смотрите на это предыдущее ТАК вопрос; у этого есть некоторая соответствующая информация: [Запечатанный Бросок Влияния Ключевого слова] [1] [1]: stackoverflow.com/questions/8912542/…
добавлено автор HaemEternal, источник
@w0lf: компилятор can' t знают, есть ли отношения между T и TOther . Поэтому I' d ожидают, что он отсрочит то решение до времени выполнения (поскольку это выполняет не - , запечатанный случай).
добавлено автор Fabian Schmied, источник

2 ответы

Так как это запечатанный класс, это не может быть унаследовано в конечном счете программистом. И чтобы иметь привилегии кастинга объектов, вам нужна иерархия наследования.

Однако в этом случае , запечатанный , ключевое слово гарантирует компилятор, который TOther не может иметь типа T в абсолютно никаком случае (т.е. Это не может быть унаследовано). Следовательно ошибка.

Удаляя , запечатанный , ключевое слово работает, поскольку это создает возможность, которая TOther может иметь тип T . Следовательно ошибки не стало.

4
добавлено
Я don' t следуют за этим. Быть запечатанный doesn' t останавливаются, вы имеющий , Забавный <�последовательность> и звонящий, <�кодируете> Бросок <�объект> на нем.
добавлено автор Rawling, источник
Когда компилятор был написан, запечатанный тип couldn' t возможно удовлетворяют любые интерфейсы, это не было явно зарегистрировано как осуществление. Кодекс, который определил, мог ли бы класс осуществить интерфейс, был, вероятно, разработан на основе того предположения. Даже при том, что предположение больше не верно, люди, работающие над компилятором, вероятно, не нашли время для фиксации компилятора, чтобы приспособить тот факт.
добавлено автор supercat, источник
, запечатанный , гарантирует что , Забавный can' t быть унаследованным.
добавлено автор Hamlet Hakobyan, источник
Как действительно запечатанный </ код> гарантируют компилятор, который TOther не может иметь типа T ? Это не затрагивает T и TOther вообще, не так ли? В первую очередь, , TOther мог совпасть с T , тогда бросок, достигнет цели. Во-вторых, , TOther мог быть базовым классом T , в этом случае это будет также работать. У компилятора нет способа сказать, мог ли бы бросок добиться успеха, AFAICs.
добавлено автор Fabian Schmied, источник

Нет никаких отношений между TOther и T, который может быть определен при компиляции.

So basically you would expect to cast IFunny to a IFunny, for example, which is not going to work.

3
добавлено
Но это все еще применяется, если класс распечатывается, правильно?
добавлено автор Rawling, источник
Действительно. Mihirj' s ответ более подробно:)
добавлено автор mathieu, источник
Нет никаких отношений (между TOther и T), который может быть определен во время компиляции, но есть хороший шанс, что отношения существуют во времени выполнения. Итак, почему компилятор предотвращает бросок?
добавлено автор Fabian Schmied, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot