Почему существует NotImplementedException?

Это действительно очень меня побуждает, поэтому я надеюсь, что кто-нибудь сможет дать мне разумное обоснование того, почему все так, как есть.

NotImplementedException. Вы меня дергаете за ногу, да?

Нет, я не собираюсь прибегать к дешевке, говоря: «Погоди, метод реализован - он выдает исключение NotImplementedException». Да, верно, вы должны реализовать метод для генерирования NotImplementedException (в отличие от вызова чистой виртуальной функции в C++ - теперь это имеет смысл!). Хотя это чертовски смешно, в моей голове есть более серьезная проблема.

Мне просто интересно, как при наличии NotImplementedException можно что-нибудь сделать с .Net? Ожидается ли, что каждый вызов абстрактного метода будет заключаться в блокировку try catch для защиты от методов, которые могут быть не реализованы? Если вы поймаете такое исключение, что, черт возьми, вы должны с ним делать ??

Я не вижу способа проверить, действительно ли метод реализован, не вызывая его. Поскольку его вызов может иметь побочные эффекты, я не могу выполнить все проверки заранее, а затем запустить свой алгоритм. Мне нужно запустить свой алгоритм, поймать NotImplementedExceptions и каким-то образом откатить мое приложение до некоторого нормального состояния.

Это безумие. Безумный. Безумный. Итак, вопрос: Почему существует NotImplementedException?

В качестве упреждающего удара я не хочу, чтобы кто-либо отвечал, «потому что дизайнерам необходимо поместить это в автоматически сгенерированный код». Это ужасно. Я бы предпочел, чтобы автоматически сгенерированный код не компилировался, пока вы не предоставите реализацию. Например, автоматически созданная реализация может быть throw NotImplementedException; где NotImplementedException не определено!

Кто-нибудь когда-нибудь ловил и обрабатывал NotImplementedException? Вы когда-нибудь оставляли NotImplementedException в своем коде? Если да, то представляло ли это бомбу замедленного действия (то есть вы случайно оставили ее там) или недостаток конструкции (метод не следует реализовывать и никогда не будет вызван)?

Я также очень подозрительно отношусь к NotSupportedException ... Не поддерживается? Что за? Если он не поддерживается, почему он является частью вашего интерфейса? Может ли кто-нибудь в Microsoft указать неправильное наследование? Но я мог бы задать еще один вопрос по этому поводу, если я не получу слишком много оскорблений для этого.

Дополнительная информация:

Этот - интересное чтение на эту тему.

Кажется, существует полное согласие с Брэд Абрамс, что «NotImplementedException предназначен для функциональности, которая еще не реализована, но на самом деле должна (и будет). Что-то вроде того, что вы могли бы использовать в Начало при создании класса, получите все методы там выбрасывая NotImplementedException, а затем удалите их с помощью реального кода ... "

Комментарии из Джаред Парсонс очень слабые, и их, вероятно, следует игнорировать: NotImplementedException: генерировать это исключение, когда тип не реализует метод по какой-либо другой причине.

MSDN еще слабее по этому вопросу, просто заявляя, что «исключение, которое выдается, когда запрошенный метод или операция не реализованы».

+1 за правильный вопрос о нечеткой проблеме, заслуживающей внимания.

Mike Hofer 04.01.2009 14:46

Получу ли я значок вместе с тегом Rant?

Daniel Paull 05.01.2009 08:15

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

leppie 30.07.2009 19:46

Хорошая догадка, но ты ошибаешься. Могу только догадываться, что вы не понимаете вопроса.

Daniel Paull 31.07.2009 09:21

@Daniel - есть и более этимологический ответ. В Win32 C API было определено возвращаемое значение E_NOTIMPL. Каждое такое возвращаемое значение было сопоставлено с исключением .Net.

Heath Hunnicutt 16.11.2009 01:48

@Heath - значит, вы считаете, что NotImplementedException существует как системное исключение, из-за грехов нашего прошлого?

Daniel Paull 16.11.2009 03:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
65
6
62 867
27
Перейти к ответу Данный вопрос помечен как решенный

Ответы 27

А как насчет прототипов или незавершенных проектов?

Я не думаю, что использование исключения - плохая идея (хотя в этом случае я использую окно сообщения).

Итак, он никогда не должен попадать в производственный код? Тогда почему это часть ядра .NET? Если вам нужна эта концепция, просто «бросьте новый объект ();» с комментарием о том, что метод ожидает реализации.

Daniel Paull 04.01.2009 12:28

Кстати, я даю вам +1, потому что вы предпочитаете использовать что-то другое, а не исключение. Лично я бы добавил assert (false) и фиктивное возвращаемое значение, предполагая, что мне нужен код для компиляции.

Daniel Paull 04.01.2009 12:31

@ Дэниел Пол: но, конечно, это опаснее, потому что утверждения не будут скомпилированы в код выпуска? ...

Mitch Wheat 04.01.2009 12:34

@ Дэниел Пол: на самом деле ты пробудил мою память, и я могу вспомнить ситуацию, когда именно это произошло ...

Mitch Wheat 04.01.2009 12:38

Если вы программируете по контракту, тестируете свою систему и доказываете правильность, утверждения - это просто денди. Альтернатива просто кажется крылом и молитвой. Я - активный сторонник утверждений и правильного оформления вашего дизайна. Не должно быть удачи, которая заставляет вашу систему работать.

Daniel Paull 04.01.2009 12:40

Основное использование исключения NotImplementedException - это сгенерированный код-заглушка: таким образом вы не забудете его реализовать !! Например, Visual Studio будет явно реализовывать методы / свойства интерфейса, при этом тело генерирует исключение NotImplementedException.

@ Дэниел Пол: выброшенное исключение!

Mitch Wheat 04.01.2009 12:34

@Mitch: Предполагая, что вы вызываете код. Не все используют инструменты покрытия кода, так что это можно легко упустить.

Daniel Paull 04.01.2009 12:41

Лучше, чтобы метод генерировал исключение, чем просто «ничего не делал», потому что он не реализован. Таким образом, у вас будет шанс найти и исправить проблему.

driAn 04.01.2009 13:56

@ Дэниел Пол: и утверждение страдает той же проблемой.

Mitch Wheat 04.01.2009 13:57

@Mitch: утверждения - это инструмент для проверки условий, которые не могут (по замыслу) возникать в вашей системе - любое сработавшее утверждение указывает на ошибку программирования. Исключения указывают на обстоятельства времени выполнения, которые (не обязательно) указывают на ошибки программирования. Яблоки и апельсины.

Daniel Paull 04.01.2009 14:07

Что вы можете сделать, так это найти во всем коде NotImplementedException и убедиться, что вы не нашли ноль при выпуске.

user407665 15.12.2010 10:25

Он предназначен для поддержки довольно распространенного варианта использования - рабочего, но только частично завершенного API. Скажем, я хочу, чтобы разработчики протестировали и оценили мой API - WashDishes() работает, по крайней мере, на моей машине, но я еще не успел написать код DryDishes(), не говоря уже о PutAwayDishes(). Вместо того, чтобы молча терпеть неудачу или выдавать какое-то загадочное сообщение об ошибке, я могу совершенно ясно понять, почему DryDishes() не работает - я еще не реализовал его.

Его родственное исключение NotSupportedException имеет смысл в основном для моделей провайдеров. Многие посудомоечные машины имеют функцию сушки, поэтому она входит в интерфейс, но моя дисконтная посудомоечная машина не поддерживает ее. Я могу сообщить об этом через NotSupportedException

Но почему это системное исключение? Почему вы не можете создать собственное исключение? Почему MS сделала эту часть ядра .NET? Что касается посудомоечной машины без функции сушки - почему у нее есть метод сушки? Неправильное наследование.

Daniel Paull 04.01.2009 12:35

Почему вы предпочли бы написать свое исключение для такой ситуации?

R. Martinho Fernandes 04.01.2009 13:23

потому что тогда я могу полностью удалить его из сборок выпуска, чтобы случайно не оставить его в коде.

Daniel Paull 04.01.2009 14:00

Но у вас все еще есть свобода делать это; вы не обязаны использовать NotSupportedException. Тем не менее, ситуация возникает настолько часто, что для нее в Framework существует стандартный класс, как и положено.

Mike Hofer 04.01.2009 14:49

Исправление: NotImplementedException, хотя NotSupportedException также применимо.

Mike Hofer 04.01.2009 14:49

У вас нет такой свободы, когда все стандартные инструменты автоматически генерируют код с заглушками, которые генерируют NotImplementedException! Вы также застряли, если его используют сторонние сборки.

Daniel Paull 04.01.2009 14:52

Вы можете использовать «поиск использования» в своей среде IDE для исключения исключений. Вот почему

krosenvold 04.01.2009 15:14

@krosenvold: Вот почему? Функция IDE, определяющая дизайн платформы? Звучит в обратном направлении для меня.

Daniel Paull 04.01.2009 15:21

@Daniel Paull: NotImplementedException является частью ядра, потому что люди ленивы, если бы его не было, они бы использовали Exception, NotSupportedException, InvalidOperationException или какое-либо другое исключение.

dalle 04.01.2009 16:05

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

Ivan 05.12.2011 03:18

Re NotImplementedException - служит для нескольких целей; он обеспечивает единственное исключение, которое (например) ваши модульные тесты могут заблокировать на случай незавершенной работы. Но кроме того, он действительно делает то, о чем говорится: этого просто нет (пока). Например, «моно» бросает это повсюду для методов, которые существуют в библиотеках MS, но еще не написаны.

Re NotSupportedException - не все доступно. Например, многие интерфейсы поддерживают пару «можно ли это сделать?». / "сделай это". Если "ты сможешь это сделать?" возвращает false, вполне разумно для "do this" выбросить NotSupportedException. Примерами могут быть IBindingList.SupportsSearching / IBindingList.Find() и т. д.

Итак, должно быть исключение Mone.NotImplementedException - почему оно является частью ядра .NET? Если вы избегаете неправильного наследования, объект будет тем, чем он является, так что "вы можете это сделать?" / "сделать это" избыточны.

Daniel Paull 04.01.2009 12:37

Это определенно пахнет неправильной наследственностью.

Daniel Paull 04.01.2009 13:08

Большинство разработчиков в Microsoft знакомы с шаблонами проектирования, в которых подходит NotImplementedException. На самом деле это довольно распространенное явление.

Хорошим примером является Составной узор, где многие объекты можно рассматривать как один экземпляр объекта. Компонент используется как базовый абстрактный класс для (правильно) унаследованных конечных классов. Например, классы File и Directory могут наследовать от одного и того же абстрактного базового класса, поскольку они очень похожи по типам. Таким образом, их можно рассматривать как единый объект (что имеет смысл, если подумать о файлах и каталогах - например, в Unix все является файлом).

Итак, в этом примере будет метод GetFiles () для класса Directory, однако класс File не будет реализовывать этот метод, потому что это не имеет смысла. Вместо этого вы получаете NotImplementedException, потому что у файла нет дочерних элементов, как у каталога.

Обратите внимание, что это не ограничивается .NET - вы встретите этот шаблон во многих объектно-ориентированных языках и платформах.

Почему File не возвращает пустой список при запросе его дочерних элементов через абстрактный интерфейс?

Daniel Paull 04.01.2009 12:44

Как разработчик приложений, я бы точно этого не ожидал. Как насчет метода AddFile (), который реализуется классом Directory - чего бы вы ожидали, если бы вы вызывали его в классе File? Я ожидал исключения. Такое поведение должно быть последовательным в хорошем API.

user51346 04.01.2009 12:50

Файл - это не каталог - неправильное наследование. Изменяемые абстрактные интерфейсы необходимо разрабатывать тщательно.

Daniel Paull 04.01.2009 13:09

-1, если подклассы не могут реализовать GetFiles, тогда иерархия неверна, en.wikipedia.org/wiki/Liskov_substitution_principle

orip 04.01.2009 13:35

В моем примере файл не наследуется от каталога; вы неправильно это прочитали. Извините, это не нарушает принцип замены Лискова. Базовый абстрактный класс компонента выдает исключение. Соответствующая реализация этих методов зависит от подклассов.

user51346 05.01.2009 13:03

Возможно, это плохая аналогия, но точка зрения Джарвиса верна. Я предпочитаю просматривать составные методы, которые не могут быть реализованы, но не выполняются. Вы часто будете видеть это с виртуальными методами.

annakata 12.01.2009 15:47

Это противоречит распространенному мнению в других ответах, что ни один производственный код никогда не должен генерировать NotImplementedExceptions. Мне трудно понять, что означает «можно сделать, но не может». Если вы сказали: «Пойдет, но пока нет», то я снова счастлив - см. Принятый ответ.

Daniel Paull 16.01.2009 10:11

Microsoft очень широко использует NotImplementedException в объектных моделях Microsoft Office. Как программиста PowerPoint, это иногда сводит меня с ума! Например, когда я пытаюсь вызвать определенные методы или свойства Shape или AnimationSettings, они могут работать нормально или могут вызывать NotImplementedException в зависимости от ситуации. Я бы хотел, чтобы был способ проверить метод на NotImplementedException, не вызывая его.

Arie Livshin 04.10.2011 21:09

NotImplementedException выбрасывается для некоторого метода .NET (см. Синтаксический анализатор C# в Code DOM, который не реализован, но метод существует!) Вы можете проверить с помощью этого метода Microsoft.CSharp.CSharpCodeProvider.Parse

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

R. Martinho Fernandes 04.01.2009 14:17

Не просто «плохо», а непростительно.

Daniel Paull 04.01.2009 14:25

взгляните на этот список: blogs.msdn.com/brada/archive/2004/07/29/201354.aspx#203896

Daniel Paull 04.01.2009 15:35

Why does the NotImplementedException exist?

NotImplementedException - отличный способ сказать, что что-то еще не готово. Почему он не готов - отдельный вопрос для авторов метода. В производственном коде вы вряд ли поймаете это исключение, но если вы это сделаете, вы можете сразу увидеть, что произошло, и это намного лучше, чем пытаться выяснить, почему методы были вызваны, но ничего не произошло или даже хуже - получите какой-то «временный» результат и получите «забавные» побочные эффекты.

Is NotImplementedException the C# equivalent of Java's UnsupportedOperationException?

Нет, в .NET есть NotSupportedException

I have to run my algorithm, catch NotImplementedExceptions and the some how roll back my application to some sane state

Хороший API имеет документацию по методам XML, в которой описаны возможные исключения.

I'm very suspicious of the NotSupportedException also... Not supported? What the? If it's not supported, why is it part of your interface?

Причин может быть миллион. Например, вы можете ввести новую версию API и не хотите / не можете поддерживать старые методы. Опять же, гораздо лучше увидеть описательное исключение, чем копаться в документации или отлаживать сторонний код.

Спасибо, aku - поддержка API - использование устаревших методов мощь является разумной причиной для этого исключения. Хотя я бы предпочел увидеть исключение DeprecatedMethodException.

Daniel Paull 04.01.2009 12:46

Есть атрибут Obsolete, я бы хотел, чтобы у нас было что-то вроде атрибута NotImplemented для получения предупреждений во время компиляции.

aku 04.01.2009 12:51

@aku: отличный комментарий - это решает проблему невозможности определить, действительно ли метод реализован, перед его вызовом (не то, чтобы это когда-либо приходилось делать).

Daniel Paull 04.01.2009 13:59

Несмотря на то, что я часто использую исключение (см. Мой ответ), я бы предпочел этот атрибут, особенно если бы я мог превратить его в аспект, который генерирует исключение (NotImplemented - мой первый выбор, для ясности).

R. Martinho Fernandes 04.01.2009 14:14

Java UnsupportedOperationException также может быть .NET InvalidOperationException.

dalle 04.01.2009 15:50

Атрибут NotImplemented будет работать только в том случае, если класс напрямую (а не вызывает метод с использованием интерфейса)

dalle 04.01.2009 15:54

Исключение InvalidOperationException .Net более близко соответствует исключению IllegalStateException в Java.

Jeffrey Hantin 14.01.2010 01:52

@aku - Да, дружище. Вот что у них есть на Яве. Разработчики Java могут вызывать статический метод «Trace», например NotImplementedException.Trace («предупреждение !! не реализовано !!»); Я завидую явистам

Alex from Jitbit 16.12.2010 20:11

Что ж, отчасти согласен. Если интерфейс был создан таким образом, что не весь класс может реализовать все его части, на мой взгляд, его следовало бы разбить.

Если IList можно или нельзя изменить, его следовало разбить на две части: одну для неизменяемой части (геттеры, поиск и т. д.), А другую - для изменяемой части (сеттеры, добавление, удаление и т. д.).

Для меня это звучит как потенциальное минное поле. В далеком прошлом я однажды работал над унаследованной сетевой системой, которая работала без остановок в течение многих лет и перестала работать более одного дня. Когда мы отследили проблему, мы обнаружили некоторый код, который явно не был закончен и который никогда не мог бы сработать - буквально, как будто программист был прерван во время его написания. Было очевидно, что этот конкретный путь кода никогда раньше не использовался.

Закон Мерфи гласит, что нечто подобное просто напрашивается на случай NotImplementedException. В наши дни TDD и т. д., Его следует забрать перед выпуском, и, по крайней мере, вы можете использовать grep-код для этого исключения перед выпуском, но все же.

При тестировании трудно гарантировать охват каждого случая, и это похоже на то, что это усложняет вашу работу, делая проблемы времени выполнения тем, что могло быть проблемами времени компиляции. (Я думаю, что аналогичный вид «технического долга» связан с системами, которые в значительной степени полагаются на «утиную печать», хотя я признаю, что они очень полезны).

Ответ принят как подходящий

Есть одна ситуация, которую я считаю полезной: TDD.

Я пишу свои тесты, затем создаю заглушки, чтобы тесты компилировались. Эти заглушки не делают ничего, кроме throw new NotImplementedException();. Таким образом, тесты по умолчанию не пройдут, несмотря ни на что. Если бы я использовал какое-то фиктивное возвращаемое значение, оно могло бы генерировать ложные срабатывания. Теперь, когда все тесты компилируются и терпят неудачу из-за отсутствия реализации, я занимаюсь этими заглушками.

Поскольку я никогда не использую NotImplementedException ни в какой другой ситуации, ни один NotImplementedException никогда не перейдет в код выпуска, так как он всегда приводит к провалу некоторых тестов.

Вам не нужно ловить это повсюду. Хорошие API документируют возникшие исключения. Это те, которые вам следует искать.

Обновлено: Я написал правило FxCop, чтобы найти их.

Это код:

using System;
using Microsoft.FxCop.Sdk;

/// <summary>
/// An FxCop rule to ensure no <see cref = "NotImplementedException"/> is
/// left behind on production code.
/// </summary>
internal class DoNotRaiseNotImplementedException : BaseIntrospectionRule
{
    private TypeNode _notImplementedException;
    private Member _currentMember;

    public DoNotRaiseNotImplementedException()
        : base("DoNotRaiseNotImplementedException",
               // The following string must be the assembly name (here
               // Bevonn.CodeAnalysis) followed by a dot and then the
               // metadata file name without the xml extension (here
               // DesignRules). See the note at the end for more details.
               "Bevonn.CodeAnalysis.DesignRules",
               typeof (DoNotRaiseNotImplementedException).Assembly) { }

    public override void BeforeAnalysis()
    {
        base.BeforeAnalysis();
        _notImplementedException = FrameworkAssemblies.Mscorlib.GetType(
            Identifier.For("System"),
            Identifier.For("NotImplementedException"));
    }

    public override ProblemCollection Check(Member member)
    {
        var method = member as Method;
        if (method != null)
        {
            _currentMember = member;
            VisitStatements(method.Body.Statements);
        }
        return Problems;
    }

    public override void VisitThrow(ThrowNode throwInstruction)
    {
        if (throwInstruction.Expression != null &&
            throwInstruction.Expression.Type.IsAssignableTo(_notImplementedException))
        {
            var problem = new Problem(
                GetResolution(),
                throwInstruction.SourceContext,
                _currentMember.Name.Name);
            Problems.Add(problem);
        }
    }
}

И это метаданные правила:

<?xml version = "1.0" encoding = "utf-8" ?>
<Rules FriendlyName = "Bevonn Design Rules">
  <Rule TypeName = "DoNotRaiseNotImplementedException" Category = "Bevonn.Design" CheckId = "BCA0001">
    <Name>Do not raise NotImplementedException</Name>
    <Description>NotImplementedException should not be used in production code.</Description>
    <Url>http://stackoverflow.com/questions/410719/notimplementedexception-are-they-kidding-me</Url>
    <Resolution>Implement the method or property accessor.</Resolution>
    <MessageLevel Certainty = "100">CriticalError</MessageLevel>
    <Email></Email>
    <FixCategories>NonBreaking</FixCategories>
    <Owner></Owner>
  </Rule>
</Rules>

Для этого вам необходимо:

  • ссылки Microsoft.FxCop.Sdk.dll и Microsoft.Cci.dll

  • Поместите метаданные в файл с именем DesignRules.xml и добавьте его в качестве встроенного ресурса в вашу сборку.

  • Назовите вашу сборку Bevonn.CodeAnalysis. Если вы хотите использовать разные имена для метаданных или файлов сборки, убедитесь, что вы соответствующим образом изменили второй параметр базового конструктора.

Затем просто добавьте полученную сборку в правила FxCop и удалите эти чертовы исключения из своего драгоценного кода. Есть некоторые угловые случаи, когда он не будет сообщать об исключении NotImplementedException, когда оно выбрасывается, но я действительно думаю, что вы безнадежны, если на самом деле пишете такой ктулийский код. Для нормального использования, то есть throw new NotImplementedException();, он работает, и это все, что имеет значение.

Я полностью согласен. Добавить это в любую другую настройку - это все равно, что иметь на вашей веб-странице знак «В разработке».

Øyvind Skaar 04.01.2009 13:40

Хороший. Однако почему NotImplementedException является частью ядра .NET? Я бы предпочел, чтобы эта концепция была привязана к поставщику, и я бы условно скомпилировал свое NotImplementedException во всех сборках общедоступных релизов. Это не концепция ядра .NET.

Daniel Paull 04.01.2009 13:56

Что в нем причиняет вред? Для меня это экономит время на написание глупого исключения. И с моим подходом мне не нужно его компилировать. Я могу гарантировать, что он никогда не используется в коде выпуска. И это точно не делает структуру намного больше ...

R. Martinho Fernandes 04.01.2009 14:09

Хорошо, я говорю вам, что это исключение может быть не лучшим решением. Я бы предпочел идею аспекта.

R. Martinho Fernandes 04.01.2009 14:14

@ Мартиньо: да, детка, ты придешь.

Daniel Paull 04.01.2009 14:21

@Martinho: означает добавить, что повреждение, вызванное его нахождением в ядре, заключается в том, что вы не можете удалить его из своей сборки, поэтому можно отправить продукт или патч, в котором все еще есть эти неприятные глючники. Я предпочитаю технику, которая заставляет невозможно совершать такую ​​ошибку.

Daniel Paull 04.01.2009 14:24

@Daniel: Вы удаляете его из своего кода, реализуя эту функцию. Я не понимаю, в чем заключается путаница (простите меня, если это звучит нелепо, этого не должно быть).

Mike Hofer 04.01.2009 14:53

@Daniel: объедините функцию NotImplemented с TDD, чтобы обеспечить реализацию функции; как только функция будет реализована, удалите исключение. Он никогда не выпускает код. NotSupportedException предназначено для поставщиков, хорошо документировано и ДОЛЖНО быть обнаружено клиентами.

Mike Hofer 04.01.2009 14:54

@Mike: если он никогда не использовался в выпущенном коде, почему он находится в ядре .NET? Если он никогда не попадает в выпущенный код, его не нужно ни документировать, ни отлавливать. PS: ваш тон меня просто устраивает! Трудно оставаться мягким и мягким за 300 символов.

Daniel Paull 04.01.2009 15:02

@Daniell Paull. Очень приятно иметь это в ядре .net, потому что это представляет собой стандартизованный, несформированный способ, с помощью которого я могу "находить способы использования" в моей среде IDE для выявления незавершенного материала.

krosenvold 04.01.2009 15:16

@krosenvold: функция IDE, определяющая дизайн платформы? Звучит в обратном направлении для меня.

Daniel Paull 04.01.2009 15:22

@krosenvold: Вы можете «найти использования» с помощью XYZException. Это будет работать так же. Вам просто нужно написать XYZException самостоятельно.

R. Martinho Fernandes 04.01.2009 15:53

Я принял это как «правильный» ответ, поскольку я согласен с таким использованием исключения. Это использование все еще кажется мне опасным, но с правильными сдержками и противовесами такое использование разумно.

Daniel Paull 04.01.2009 16:46

Мне нравится идея использования FxCop для двойной проверки отсутствия NotImplementedExceptions. Я использовал его в одном из своих проектов и обнаружил одну небольшую ошибку. В VisitThrow вам нужно проверить, что значение throwInstruction.Expression не равно нулю. Это происходит всякий раз, когда кто-то перебрасывает голым «броском»; инструкция. Кроме этого, большое спасибо!

Grhm 10.02.2010 16:42

+1 За ктулхианский код. Лучшее прилагательное, которое я когда-либо слышал для обозначения плохого кода.

Josh 02.08.2011 03:18

К сожалению, в последнее время я по локоть в ктулхийском коде. Нет NotImplementedExceptions, о которых я знаю, но я бы предпочел функцию, которой не существует, той, которая существует только для объятий щупальцами.

Wayne Werner 24.10.2012 00:43

Редко использую для исправления интерфейса. Предположим, что у вас есть интерфейс, которому необходимо соответствовать, но определенный метод никогда не будет вызван кем-либо, поэтому просто вставьте NotImplementedException, и если кто-то вызовет его, они будут знать, что делают что-то не так.

Метод интерфейса, который нельзя вызвать? Какого черта?

Daniel Paull 04.01.2009 13:51

Если вы не реализуете весь интерфейс, не реализуйте его. С этой методологией вы должны использовать языки, которые умеют не печатать, например Python или даже C# 4 :(.

R. Martinho Fernandes 04.01.2009 14:37

Итак, у вас есть 10 классов, реализующих интерфейс, но у одного или нескольких из них есть дополнительные методы, которые вам нужно вызвать. Как это сделать? Я реализую интерфейс с дополнительным методом и вызываю его, если тип совпадает. Какое у вас решение? 10 отдельных классов?

dr. evil 04.01.2009 16:09

@Slough: дайте мне пример, где это так, и я исправлю ваш дизайн бесплатно.

Daniel Paull 04.01.2009 16:32

В IDataReader есть масса методов. Мне пришлось реализовать его интерфейс, прежде чем я узнал, что мне понадобятся только три метода. Интерфейс находится в платформе .net. Я не могу это изменить. Я также передаю его классу фреймворка, который не могу изменить. Это плохой интерфейс, но я застрял в нем.

Mike Two 04.01.2009 18:08

@Mike: Я чувствую твою боль, и этот сценарий может быть верен, поскольку твою руку заставили. Поэтому MS включила это плохое исключение, чтобы поддержать их плохой интерфейс и дизайн фреймворка. Разумный аргумент. Я думаю, что в данном случае две ошибки только усугубили ситуацию.

Daniel Paull 05.01.2009 02:30

Случай с IDataReader и друзьями указывает на использование. В большинстве случаев используется только подмножество его методов. При построении интерфейса как оболочки неиспользуемые заглушки должны что-то делать. Это самый разумный поступок.

Joshua 22.11.2012 22:40

Почему вы чувствуете необходимость перехватывать все возможные исключения? Вы тоже оборачиваете каждый вызов метода с помощью catch (NullReferenceException ex)?

Код заглушки, бросающий NotImplementedException, является заполнителем, если он заставляет его выпустить, это должно быть ошибкой, как и NullReferenceException.

Если используется просто как заполнитель, почему NotImplementedException является частью ядра .NET? Я бы предпочел, чтобы эта концепция была привязана к поставщику, и я бы условно скомпилировал свое NotImplementedException во всех сборках общедоступных релизов. Это не концепция ядра .NET.

Daniel Paull 04.01.2009 13:50

@Daniel, я думаю, у нас разные мнения по этому поводу, но я бы определенно не компилировал исключения в сборках релизов, точно так же, как я бы не ловил NullReferenceException - я бы исправил ошибку.

orip 05.01.2009 11:00

@orip: Я думаю, вы неправильно поняли. Компилируйте класс NotImplementedException, а не места, где он использовался. Это приведет к тому, что любое случайное использование NotImplementedException станет ошибкой компиляции.

Daniel Paull 12.01.2009 15:25

@ Дэниел: ах, в этом есть смысл.

orip 14.01.2009 01:05

В моем коде есть несколько NotImplementedExceptions. Часто это происходит из части интерфейса или абстрактного класса. Некоторые методы, которые, как мне кажется, могут мне понадобиться в будущем, имеют смысл как часть класса, но я просто не хочу тратить время на добавление, если оно мне действительно не понадобится. Например, у меня есть интерфейс для всех отдельных видов статистики в моей игре. Одним из таких типов является ModStat, который представляет собой сумму базовой характеристики плюс все модификаторы (например, оружие, броня, заклинания). В моем интерфейсе статистики есть событие OnChanged, но мой ModStat работает, вычисляя сумму всех статистических данных, на которые он ссылается при каждом вызове. Таким образом, вместо того, чтобы создавать тонну событий ModStat.OnChange каждый раз при изменении статистики, у меня просто генерируется NotImplementedException, если кто-то пытается добавить / удалить слушателя в OnChange.

Все языки .NET - это продуктивность, так зачем тратить время на кодирование того, что вы даже не будете использовать?

"Так зачем тратить время на кодирование того, что ты даже не будешь использовать?" Интересно - похоже, что вы реализовали заглушки, которые, возможно, никогда не реализовать. Следуйте своему собственному совету, и исключение NotImplementedException вам не понадобится!

Daniel Paull 04.01.2009 14:14

Один Даниил сказал, что вы не должны писать заглушки напрасно. Если они вам «могут» понадобиться в будущем, напишите их в будущем. В большинстве случаев сборки .NET версии очень хорошо.

R. Martinho Fernandes 04.01.2009 14:34

«Следуйте своему собственному совету, и вам не понадобится NotImplementedException!» Смысл исключения здесь в том, что вы можете скомпилировать, но все еще терпят неудачу, если вызывается метод, и знаете, почему ваш код не удался. Добавьте код, если получите исключение - вот и все.

Spodi 08.01.2009 13:36

Почему бы не создать собственный тип исключения? Почему это основная концепция .net?

Daniel Paull 12.01.2009 15:28

NotImplementedException

Исключение возникает, когда запрошенный метод или операция не реализованы.

Создание этого единственного исключения, определенного в ядре .NET, упрощает их поиск и устранение. Если бы каждый разработчик создал свой собственный ACME.EmaNymton.NotImplementedException, было бы труднее найти их всех.

NotSupportedException

Исключение возникает, когда вызываемый метод не поддерживается.

Например, когда есть попытка чтения, поиска или записи в поток, который не поддерживает вызываемую функциональность.

Например, сгенерированные итераторы (с использованием ключевого слова yield) - это IEnumerator, но метод IEnumerator.Reset выдает NotSupportedException.

«облегчает их поиск и искоренение» - проще? Это твоя причина? Не потому, что это правильный способ, а потому, что это самый простой способ. Хороший мужчина.

Daniel Paull 04.01.2009 14:56

Почему поток, который не поддерживает произвольный доступ, имеет метод поиска? Не будем прятаться за плохим дизайном потокового интерфейса Microsoft.

Daniel Paull 04.01.2009 14:57

Теперь я боюсь называть Reset () любым перечислителем.

Daniel Paull 04.01.2009 14:57

Конечно, INotResetEnumerator, возможно, был бы лучше, от которого происходит IEnumerator. Но приводит к слишком большому количеству занятий.

dalle 04.01.2009 15:14

Было бы интересно правильно его спроектировать. Я не согласен с тем, что это приведет к слишком большому количеству интерфейсов.

Daniel Paull 04.01.2009 15:25

Все зависит от степени детализации, у вас может быть IListMutable (который содержит Add, Clear, Insert, Remove, RemoveAt) и IListImmutable (Contains, CopyTo, GetEnumerator, IndexOf). MyList: IListMutable, IListImmutable {/ * impl * /}

dalle 04.01.2009 15:42

Но что, если вам нужен список только для добавления и только для чтения? MyList: IListAdd, IListInsert, IListImmutable {/ * impl * /} и пусть IListMutable: IListAdd, IListClear, IListInsert, IListRemove, IListRemoveAt

dalle 04.01.2009 15:44

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

Daniel Paull 04.01.2009 16:43

Похоже, вы предлагаете, чтобы разработчик любого интерфейса всегда мог угадывать все варианты использования интерфейса, как оракул. Конечно, в рамках одного проекта это возможно; в общем, я думаю, что нет.

Zach Snow 14.03.2009 11:33

@zacharyrsnow: Если следовать здравым принципам объектно-ориентированного дизайна, то интерфейсы будут интуитивно понятными и будут служить ясной цели. Поскольку цель ясна, никаких суперсил (например, оракула) во время проектирования не требуется. Так что в целом я так думаю ...

Daniel Paull 15.04.2009 12:16

@dalle: правильным дизайном было бы, чтобы IEnumerable не предоставлял сброс, но предоставлял довольно слабые гарантии поведения перечисления при обновлении коллекции (выброс исключения был бы вариантом, но не обязательным, если бы все элементы, которые существуют во всем перечислении возвращаются ровно один раз и т. д.); IMultipassEnumerable добавит Reset, FastCount и Count (FastCount вернет по своему выбору либо -1, либо правильный счетчик; его можно использовать для предварительного выделения места для списка, если размер коллекции был известен до того, как он был полностью перечислен) .

supercat 10.03.2011 01:14

Я думаю, есть много причин, по которым MS добавила NotImplementedException в фреймворк:

  • Для удобства; так как многим разработчикам он понадобится во время разработки, почему каждый должен сворачивать свои собственные?
  • Так что инструменты могут полагаться на его присутствие; например, команда Visual Studio «Реализовать интерфейс» создает заглушки методов, которые вызывают исключение NotImplementedException. Если бы этого не было во фреймворке, это было бы невозможно или, по крайней мере, было бы довольно неудобно (например, он мог бы генерировать код, который не компилируется, пока вы не добавите свое собственное NotImplementedException)
  • Поощрять последовательную «стандартную практику»

Франкодвайер считает NotImplementedException потенциальной бомбой замедленного действия. Я бы сказал, что любой незаконченный код - это бомба замедленного действия, но NotImplementedException гораздо легче обезвредить, чем альтернативы. Например, ваш сервер сборки может сканировать исходный код для всех случаев использования этого класса и сообщать о них как о предупреждениях. Если вы действительно хотите его забанить, вы можете даже добавить в свою систему управления версиями ловушку перед фиксацией, которая предотвращает регистрацию такого кода.

Конечно, если вы выбросите собственное NotImplementedException, вы можете удалить его из окончательной сборки, чтобы убедиться, что не осталось бомб замедленного действия. Но это будет работать только в том случае, если вы будете использовать свою собственную реализацию последовательно во всей команде, и вы должны убедиться, что не забыли удалить ее перед выпуском. Кроме того, вы можете обнаружить, что не можете удалить его; возможно, есть несколько приемлемых вариантов использования, например, при тестировании кода, который не поставляется клиентам.

Почему бы не иметь «Microsoft.Development.Support» или аналогичную сборку, в которой есть полезные классы и утилиты (включая NotImplementedException). Намерение состоит в том, чтобы ссылаться на эту сборку в сборках разработчика, но не в выпущенном коде?

Daniel Paull 04.01.2009 15:18

Для этого потребуется добавить ссылку на сборку Microsoft.Development.Support для каждого проекта, который ее использует, что создаст еще одно неудобство и препятствие для инструментов.

oefe 04.01.2009 16:40

А проблема с этим есть? Я бы предпочел, чтобы моя система была исправлена, что доставляет небольшие неудобства моим разработчикам. Было бы удобнее использовать библиотеки DLL, но выгода оправдывает затраты (под стоимостью я имею в виду усилия и сложность).

Daniel Paull 05.01.2009 03:48

Я обобщу свои взгляды по этому поводу в одном месте, поскольку они разбросаны по нескольким комментариям:

  1. Вы используете NotImplementedException, чтобы указать, что член интерфейса еще не реализован, но будет. Вы комбинируете это с автоматическим модульным тестированием или тестированием QA, чтобы определить функции, которые еще необходимо реализовать.

  2. Как только функция будет реализована, вы удалите NotImplementedException. Для этой функции написаны новые модульные тесты, чтобы убедиться, что она работает должным образом.

  3. NotSupportedException обычно используется поставщиками, которые не поддерживают функции, не имеющие смысла для определенных типов. В этих случаях определенные типы вызывают исключение, клиенты перехватывают их и обрабатывают соответствующим образом.

  4. Причина того, что и NotImplementedException, и NotSupportedException существуют в Framework, проста: ситуации, которые к ним приводят, являются обычными, поэтому имеет смысл определить их в Framework, чтобы разработчикам не приходилось постоянно их переопределять. Кроме того, это позволяет клиентам легко узнать, какое исключение нужно перехватить (особенно в контексте модульного теста). Если вам нужно определить собственное исключение, они должны выяснить, какое исключение нужно перехватывать, что, по крайней мере, является контрпродуктивным расходом времени и часто неверным.

Вы признаете, что NotImplementedException будет удалено - в этом случае в ядре .NET нет необходимости. Это ваша личная забота о вашем собственном процессе разработки.

Daniel Paull 04.01.2009 15:15

Вот один пример: в Java всякий раз, когда вы реализуете интерфейс Iterator, вы должны переопределить очевидные методы hasNext() и next(), но есть еще и delete(). В 99% случаев, которые у меня есть, мне это не нужно, поэтому я просто кидаю NotImplementedException. Это намного лучше, чем молча ничего не делать.

Еще лучше было бы, чтобы в интерфейсе не было метода delete (). Интерфейсы звучат так же ломанно, как потоки .net.

Daniel Paull 04.01.2009 18:01

Оба они - хаки для решения двух распространенных проблем.

NotImplementedException - это обходной путь для разработчиков, которые являются астронавтами архитектуры и любят сначала записывать API, а потом код. Очевидно, что, поскольку это не инкрементный процесс, вы не можете реализовать все сразу и поэтому хотите притвориться, что вы наполовину закончили, выбрасывая NotImplementedException.

NotSupportedException - это способ обойти ограничения систем типов, подобных тем, которые существуют в C# и Java. В этих системах типов вы говорите, что Rectangle 'является' Shape, если и только если Rectangle наследует все характеристики Shapes (включая функции-члены + переменные). Однако на практике это не так. Например, Квадрат - это Прямоугольник, но Квадрат - это ограничение Прямоугольника, а не обобщение.

Поэтому, когда вы хотите унаследовать и ограничить поведение родительского класса, вы бросаете NotSupported на методы, которые не имеют смысла для ограничения.

Нет никаких причин, по которым астронавт-архитектор не может разработать разумный интерфейс, кроме как - они плохо разбираются в дизайне и не способны выполнять свою работу. Архитектор (yuk) не должен иметь последнее слово при проектировании API; перед его внедрением следует проконсультироваться с разработчиками и подписать их.

Daniel Paull 05.01.2009 02:36

Когда вы хотите унаследовать и ограничить поведение родительского класса, вы нарушаете инварианты базового класса / интерфейса. Если в контракте базового класса / интерфейса явно не указано, что реализации могут не поддерживать все функции (возможно, с шаблоном CanDo / Do ()), не делайте этого. Скорее всего, вы сломаете клиентский код. Если вам нужно разорвать контракт Rectangle для создания класса Square, Square это не (т.е.не наследуется от) Rectangle. Я знаю, что легко рассматривать наследование как «есть», но иногда это может быть очень плохой метафорой.

R. Martinho Fernandes 27.06.2010 22:43

@Afd - Я предлагаю вам почитать. «Квадрат - это особый прямоугольник» - это повсеместный пример, показывающий, где люди ошибаются при наследовании.

Edward 11.04.2011 17:13

На самом деле нет причин для фактического ловить NotImplementedException. При попадании он должен убить ваше приложение, и сделать это очень болезненно. Единственный способ исправить это - не поймать его, а изменить исходный код (либо реализовать вызываемый метод, либо изменить вызывающий код).

Это очень странный ответ. Если никто никогда не предназначен для перехвата исключения, зачем его бросать и почему оно является частью ядра .Net? ПРИМЕЧАНИЕ: то, что вы генерируете исключение, не означает, что оно не будет обнаружено. Почему не просто Assert (false) как в отладочной, так и в выпускной сборках?

Daniel Paull 05.01.2009 02:25

Что бы вы сделали в оговорке о вылове? Специально для NotImplementedException?

jeroenh 05.01.2009 02:38

Если бы я поступил по-своему, я бы никогда не бросил и не поймал NotImplementedException. Я пытаюсь найти причину, по которой он является частью основной библиотеки.

Daniel Paull 05.01.2009 03:43

Есть много других исключений, которые вы не должны улавливать (StackOverflowException, OutOfMemoryException).

jeroenh 16.09.2011 12:14

Это исключение необходимо для COM-взаимодействия. Это E_NOTIMPL. Связанный блог также показывает другие причины

Если единственное допустимое использование - сопоставление с COM E_NOTIMPL, то это исключение обязательно должно быть в пространстве имен взаимодействия. Какие еще допустимые варианты использования размещены в этом блоге? Аргумент, что это указывает на временное состояние развития, неубедителен; используйте для этого собственное исключение.

Daniel Paull 06.01.2009 01:42

Из ECMA-335, спецификация CLI, в частности типы библиотеки CLI, System.NotImplementedException, раздел примечаний:

«Некоторые типы и конструкции, указанные в других частях настоящего стандарта, не требуются для реализаций интерфейса командной строки, которые соответствуют только профилю ядра. Например, набор функций с плавающей запятой состоит из типов данных с плавающей запятой System.Single и System.Double. Если поддержка для них исключена из реализации, любая попытка ссылаться на подпись, которая включает типы данных с плавающей запятой, приводит к исключению типа System.NotImplementedException ".

Таким образом, исключение предназначено для реализаций, реализующих только минимальные профили соответствия. Минимально необходимый профиль - это профиль ядра (см. ECMA-335 4-е издание - раздел IV, раздел 3), который включает BCL, поэтому исключение включено в «основной API», а не в какое-либо другое место.

Использование исключения для обозначения зарезервированных методов или для методов, созданных конструктором, не имеющих реализации, означает неправильное понимание цели исключения.

Я не понимаю, почему эта информация НЕ включена в документацию MSDN для реализации интерфейса командной строки MS.

Я не могу поручиться за NotImplementedException (я в основном согласен с вашим мнением), но я широко использовал NotSupportedException в основной библиотеке, которую мы используем на работе. DatabaseController, например, позволяет вам создать базу данных любого поддерживаемого типа, а затем использовать класс DatabaseController во всем остальном коде, не слишком заботясь о типе базы данных под ней. Довольно простые вещи, правда? Если NotSupportedException пригодится (и где я бы использовал свою собственную реализацию, если бы она еще не существовала), это два основных экземпляра:

1) Перенос приложения в другую базу данных Часто утверждают, что это редко, если вообще когда-либо, случается или необходимо. Фигня * т. Убирайся больше.

2) Та же база данных, другой драйвер Самый последний пример этого - когда клиент, использующий приложение с поддержкой Access, обновился с WinXP до Win7 x64. Поскольку 64-битный драйвер JET отсутствует, их ИТ-специалист установил вместо этого AccessDatabaseEngine. Когда у нашего приложения произошел сбой, мы могли легко увидеть из журнала, что это был сбой DB.Connect с NotSupportedException, который мы быстро смогли устранить. Другой недавний пример - один из наших программистов, пытающийся использовать транзакции в базе данных Access. Несмотря на то, что Access поддерживает транзакции, наша библиотека не поддерживает транзакции Access (по причинам, выходящим за рамки данной статьи). NotSupportedException, ваше время сиять!

3) Общие функции Я не могу придумать здесь краткий пример «из опыта», но если вы думаете о чем-то вроде функции, которая добавляет вложение к электронному письму, вы хотите, чтобы она могла принимать несколько распространенных файлов, таких как JPEG, все, что получено из различных потоковые классы и практически все, что имеет метод ".ToString". Что касается последней части, вы, конечно, не можете учитывать все возможные типы, поэтому сделайте их универсальными. Когда пользователь передает OurCrazyDataTypeForContainPrivateSpreadsheetData, используйте отражение, чтобы проверить наличие метода ToString, и вернуть NotSupportedException, чтобы указать на отсутствие поддержки указанных типов данных, которые не поддерживают ToString.

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

Выброс NotImplementedException - наиболее логичный способ для IDE сгенерировать код заглушки компиляции. Например, когда вы расширяете интерфейс и заставляете Visual Studio вставлять его за вас.

Если вы немного использовали C++ / COM, он тоже существовал, за исключением того, что он был известен как E_NOTIMPL.

Для него есть допустимый вариант использования. Если вы работаете над определенным методом интерфейса, вы хотите, чтобы код компилировался, чтобы вы могли его отлаживать и тестировать. Согласно вашей логике вам нужно будет удалить метод из интерфейса и закомментировать некомпилируемый код-заглушку. Это очень фундаменталистский подход, и, хотя он имеет свои достоинства, не все будут или должны его придерживаться. Кроме того, большую часть времени вы хотите, чтобы интерфейс был законченным.

Наличие NotImplementedException прекрасно определяет, какие методы еще не готовы, в конце концов, это так же просто, как нажать Ctrl+Shift+F, чтобы найти их все, я также уверен, что инструменты статического анализа кода тоже это подберут.

Вы не должны отправлять код с исключением NotImplementedException. Если вы думаете, что, не используя его, вы можете улучшить свой код, продолжайте, но есть более продуктивные вещи, которые вы можете сделать, чтобы улучшить качество исходного кода.

«Согласно вашей логике, вам нужно удалить метод из интерфейса и закомментировать некомпилируемый код-заглушку». Давайте не будем вкладывать слова в мой рот - я бы никогда не посоветовал вам это сделать. Я согласен, что во время разработки у вас будут нереализованные заглушки. Но эти заглушки могут вызвать ваше собственное исключение. Я просто не понимаю, почему NotImplementedException должно существовать как часть основных библиотек .Net.

Daniel Paull 14.01.2010 15:24

Что ж, в этом случае вы выполнили обычный StackOverflow и не спросили, что вы действительно хотели спросить. Ваш собственный ответ достаточно лаконично отвечает на ваш вопрос, но я, и я уверен, что другие читают ваш вопрос как «Вы не должны бросать исключения для нереализованных методов».

Igor Zevaka 15.01.2010 01:45

Зачем выбрасывать собственные исключения, если для этого есть стандарт? Повторное изобретение колеса - одна из основных причин, почему работа в «нашей» отрасли иногда бывает такой болезненной (синдром NIH ...). В некоторых местах вам могут понадобиться заглушки, и создание стандартизированного исключения позволяет легко отслеживать их с помощью инструментов. например, "grep". Я также часто использую NIE с TDD. Есть много мест, где они имеют смысл. Просто оставить заглушку иногда даже более опасно, я люблю спамить свой код с помощью "// TODO:", потому что, как только он записан, я не могу его забыть.

Tom 04.11.2010 17:58

Две причины:

  1. Во время разработки методы игнорируются и вызывают исключение, чтобы напомнить разработчикам, что написание их кода еще не завершено.

  2. Реализация интерфейса подкласса, который по замыслу не реализует один или несколько методов унаследованного базового класса или интерфейса. (Некоторые интерфейсы слишком общие.)

Если вы работаете с интерфейсами, которые «слишком общие» для класса, который вы пишете, вам, вероятно, следует подумать об интерфейсе, который имеет только те методы, которые вам действительно нужны. Если у IFooBar есть три метода, а у меня есть экземпляр IFooBar, эти методы лучше реализовать (или, по крайней мере, генерировать исключения, определенные контрактом). Я бы сказал, что 95% или более случаев выброса NotImplementedException () будет нарушением принципа замены Лискова.

Doctor Blue 14.01.2010 02:46

Да, но иногда у вас нет выбора, например, когда вы используете стандартную библиотеку .NET. Рассмотрим некоторые из «необязательных» методов в классах итератора и потоков ввода-вывода.

David R Tribble 14.01.2010 03:33

@S. ДеПоу: Это может не нарушать принцип замещения Лискова, если есть другой способ определить, следует ли вызывать метод во время выполнения, например, тест CanXXX (), который сообщает вам, что вы можете вызвать XXX (). Однако я очень подозрительно отношусь к такого рода интерфейсам, поскольку они пахнут неправильным наследованием - как и (2) в этом ответе.

Daniel Paull 14.01.2010 15:32

Если вы не хотите его использовать, просто проигнорируйте его. Если у вас есть блок кода, успех которого зависит от успеха каждой его части, но он может дать сбой между ними, тогда ваш единственный вариант - поймать базовый Exception и откатить то, что нужно откатить. Забудьте о NotImplementedException. Может быть множество исключений, таких как MyRandomException, GtfoException и OmgLolException. После того, как вы изначально напишите код, я мог бы подойти и выбросить ДРУГОЙ тип исключения из API, который вы вызываете. Тот, которого не существовало, когда вы писали свой код. Обрабатывайте те, которые умеете обрабатывать, и откатывайте все остальные, например, catch(Exception). Думаю, это довольно просто ... Я тоже считаю, что это пригодится. Особенно, когда вы пробуете необычные вещи с языком / фреймворком, которые иногда навязывают вам что-то.

У меня есть один пример - сериализация. Я добавил в свою библиотеку .NET свойства, которых нет в базе данных (например, удобные оболочки для существующих «тупых» свойств, таких как свойство FullName, объединяющее FirstName, MiddleName и LastName). Затем я хочу сериализовать эти типы данных в XML, чтобы отправить их по сети (например, из приложения ASP.NET в JavaScript), но структура сериализации сериализует только общедоступные свойства с помощью средств доступа как get, так и set. Я не хочу, чтобы вы могли установить FullName, потому что тогда мне придется разбирать его, и может быть какой-то непредвиденный формат, который я неправильно разбираю, и целостность данных вылетает из окна. Для этого проще просто использовать базовые свойства, но поскольку язык и API требуют, чтобы у меня был аксессуар set, я выброшу NotImplementedException (я не знал о NotSupportedException, пока не прочитал эту ветку, но любой из них работает) так что если какой-нибудь программист в будущем все же попытается установить FullName, он обнаружит исключение во время тестирования и осознает свою ошибку.

catch (Exception) или аналогичный catch (...) в C++ - одна из самых злобных вещей, которые вы можете сделать в программировании. Это называется «подмести под ковер» и начинается ваше погружение в Большой шар грязи. Помещение catch (Exception) куда угодно непросто и непросто - если вы думаете, что это так, то вам предстоит пройти долгий путь, прежде чем вы сможете написать надежный код. В вашем примере, если FullName считается неизменяемым (т. Е. Не может быть установлено), почему в API есть установщик для него? Что-то не так с вашим (или Microsoft) дизайном. Есть множество способов избежать добавления этого сеттера ...

Daniel Paull 28.06.2010 05:53
catch(Exception) - это именно то, что вам нужно в «верхней части» приложения, где, если бы исключение было иначе оставлено необработанным, среда выполнения должна была бы обработать его вместо этого, что обычно уродливо и неприятно для пользователя. По сути, это крах. Примеры находятся в Main или в Page_Load. У свойства FullName есть сеттер, потому что он требуется для API сериализации, как я сказал в сообщении, которое вы прокомментировали ...
bambams 07.07.2010 22:50

NotImplementedException существует только для облегчения разработки. Представьте, что вы начинаете реализацию интерфейса. Вы хотели бы иметь возможность по крайней мере построить, когда вы закончите реализацию одного метода, прежде чем переходить к следующему. Замещение методов NotImplemented с помощью NotImplementedExceptions - отличный способ сохранить незаконченный код, который очень легко обнаружить позже. В противном случае вы рискуете быстро реализовать что-то, что можете забыть исправить.

Вы можете использовать любую методологию, которая вам нравится, так что вы можете «заглушить» все, что захотите. Зачем Microsoft поместила это в стандартную библиотеку? Вы можете так же легко определить собственное исключение, которое нужно выбросить. Если вы использовали свой собственный класс исключения, вы можете удалить определение класса из своего кода, и компилятор сообщит вам, если вы забыли заменить одну из своих заглушек реальной реализацией - мне это нравится намного больше, чем поиск шаблонов в текст ... Обратите внимание, что вы не можете удалить NotImplementedException из сборки, поэтому это не вариант, если вы его используете.

Daniel Paull 16.12.2010 05:01

Допустим, у вас есть этот метод в вашем производственном коде

public void DoSomething()

Какой из них вы бы выбрали, если хотите, чтобы его закончили позже?

public void DoSomething()
{
}

или же

public void DoSomething()
{
    throw new NotImplementedException();
}

Я бы обязательно взял второй. В сочетании с Elmah или любым другим механизмом регистрации ошибок, который у вас есть (реализован как аспект всего вашего приложения). Вместе с фильтрацией журнала / исключений для запуска уведомления по электронной почте о критической ошибке, когда она обнаружена.

Аргумент, что NotImplementedException == незаконченный, также неверен. (1) Выявление нереализованных методов следует оставить на усмотрение модульных / интеграционных тестов. Если у вас 100% покрытие (что вы должны сделать сейчас с таким количеством инструментов для создания макетов / заглушек / кода) без NotImplementedException, о чем вы беспокоитесь? (2) Генерация кода. Просто просто. Опять же, если я сгенерирую код и использую только половину сгенерированного кода, почему бы мне не иметь NotImplementedException в остальной части сгенерированной заглушки?

Это как сказать, что код не должен компилироваться, если каждый ввод, допускающий значение NULL, не должен проверяться / обрабатываться на значение NULL. (ИНАЧЕ ошибка в триллион долларов, если не больше). Язык должен быть гибким, а тесты / контракты - твердыми.

Хуже того, как насчет Point ComputeLocation() { return default(Point); }. Есть много случаев, когда правильное поведение для метода без возвращаемого значения - просто ничего не делать (например, многие классы реализуют IDisposable.Dispose() как бездействующий), но наличие метода, возвращающего тип структуры, возвращает экземпляр по умолчанию, как если бы это был реальная стоимость кажется действительно сомнительной.

supercat 19.06.2013 00:51

Другие вопросы по теме