Прошу отличаться от @ nobugz . E_NOINTERFACE
имеет очень конкретное значение, что ваш объект не поддерживает определенный интерфейс, который только что запросил ваш клиент.
В общем случае вы должны возвращать E_NOINTERFACE
только из своих IUnknown::QueryInterface()
. Возвращение E_NOINTERFACE
из DoStuff()
удивит как конечных пользователей, так и инструменты. Если бы я увидел, что E_NOINTERFACE
приходит откуда-то, кроме QueryInterface()
, моей непосредственной мыслью будет «утечка абстракции!».
На первый взгляд, E_INVALIDARG
выглядит как лучшие из доступных вариантов - в конце концов, вам был передан аргумент, который не работает для вас. Но, на мой взгляд, здесь есть одна тонкость, поэтому я не уверен, смогу ли я сделать из этого универсальное правило.
В идеальном мире коды ошибок, возвращаемые методом COM, больше относятся к интерфейсу, чем к объекту. Конкретно, IWellKnownInterface::DoStuff()
не определяет (обязательно), что передаваемый объект должен реализовывать ISpecificInterface
, иначе у него будет другой тип аргумента. Таким образом, технически вы обманываете потенциальных пользователей вашего объекта, не полностью реализуя семантику вашего интерфейса. Конечно, в реальном мире очень сложно создать значимую открытую систему, если вы превратите это в абсолютное правило, а интерфейсы будут такими жесткими.
Итак: если вы можете предоставить ограниченную функциональность, которая по-прежнему соответствует семантике интерфейса, даже если ваш аргумент не реализует ISpecificInterface
, вам следует подумать об этом.
Предполагая, что вы должны вернуться с ошибкой: если это хорошо известный, хорошо документированный ( хорошо спроектированный? ) интерфейс, я, вероятно, сначала загляну в документацию по интерфейсу, чтобы увидеть, дают ли они вам любое руководство. Не имея этого, я, вероятно, пошел бы и использовал E_INVALIDARG
.
@ Phil Booth дает несколько хороших рекомендаций о том, как предоставить пользователю больше информации о природе ошибки.
Очевидно, что если бы у вас была возможность, вы бы хотели изменить интерфейс, чтобы вместо него взять ISpecificInterface* param
.