Eu me deparei com esta situação. De fato, como apontado em outro lugar, o BCL tem tais instâncias ... tentarei fornecer melhores exemplos e fornecer algumas justificativas:
Quando você já possui uma interface que mantém por motivos de compatibilidade e ...
A interface contém membros obsoletos ou descartados. Por exemplo BlockingCollection<T>.ICollection.SyncRoot(entre outros), embora ICollection.SyncRootnão seja obsoleto, ele será lançado NotSupportedException.
A interface contém membros documentados para serem opcionais e que a implementação pode gerar a exceção. Por exemplo, no MSDN sobre IEnumerator.Resetisso, diz:
O método Reset é fornecido para interoperabilidade COM. Não precisa necessariamente ser implementado; em vez disso, o implementador pode simplesmente lançar uma NotSupportedException.
Por um erro no design da interface, deveria ter sido mais de uma interface em primeiro lugar. É um padrão comum na BCL implementar versões somente leitura de contêineres NotSupportedException. Eu já fiz isso, é o que se espera agora ... faço ICollection<T>.IsReadOnlyretornotrue para que você possa dizer a eles. O design correto seria ter uma versão legível da interface e, em seguida, a interface completa herda disso.
Não há interface melhor para usar. Por exemplo, eu tenho uma classe que permite acessar itens por índice, verificar se ele contém um item e em qual índice, tem algum tamanho, você pode copiá-lo para uma matriz ... parece um trabalho, IList<T>mas minha classe tem um tamanho fixo e não suporta adicionar nem remover, por isso funciona mais como uma matriz do que como uma lista. Mas não há IArray<T>no BCL .
A interface pertence a uma API que é portada para várias plataformas e, na implementação de uma plataforma específica, algumas partes dela não são suportadas. Idealmente, haveria alguma maneira de detectá-lo, para que o código portátil que usa essa API possa decidir o que quer ou não chamar essas partes ... mas se você chamá-las, é totalmente apropriado obtê-las NotSupportedException. Isso é particularmente verdade, se for uma porta para uma nova plataforma que não estava prevista no design original.
Considere também por que não é suportado?
Às vezes InvalidOperationExceptioné uma opção melhor. Por exemplo, mais uma maneira de adicionar polimorfismo em uma classe é ter várias implementações de uma interface interna e seu código está escolhendo qual instanciar, dependendo dos parâmetros fornecidos no construtor da classe. [Isso é particularmente útil se você souber que o conjunto de opções é fixo e não deseja permitir que classes de terceiros sejam introduzidas por injeção de dependência.] Fiz isso para suportar o ThreadLocal porque a implementação de rastreamento e não rastreamento é distante demais, e o que ThreadLocal.Valueslança na implementação sem rastreamento?InvalidOperationExceptionmesmo assim, não depende do estado do objeto. Nesse caso, eu mesmo apresentei a classe e sabia que esse método tinha que ser implementado apenas lançando uma exceção.
Às vezes, um valor padrão faz sentido. Por exemplo, no ICollection<T>.IsReadOnlymencionado acima, faz sentido retornar apenas "verdadeiro" ou "falso", dependendo do caso. Então ... qual é a semântica IFoo.Bar? talvez haja algum valor padrão sensato para retornar.
Adendo: se você está no controle da interface (e não precisa ficar com ela por compatibilidade), não deve haver um caso em que você precise jogar NotSupportedException. No entanto, pode ser necessário dividir a interface em duas ou mais interfaces menores para se adequar ao seu caso, o que pode levar à "poluição" em situações extremas.