¿Por qué existe la excepción NotImplementedException?

Esto realmente me incita, así que espero que alguien me pueda dar una justificación razonable de por qué las cosas son como son.

NotImplementedException. Estás tirando de mi pierna, ¿verdad?

No, no voy a tomar la puñalada barata diciendo: “Espera, el método está implementado, arroja una NotImplementedException”. Sí, es correcto, tienes que implementar el método para lanzar una excepción NotImplementedException (a diferencia de una llamada de función virtual pura en C ++, ¡ahora eso tiene sentido!). Si bien eso es bastante divertido, hay un problema más serio en mi mente.

Me pregunto, en presencia de NotImplementedException, ¿cómo puede alguien hacer algo con .Net? ¿Se espera que envuelva cada llamada a método abstracto con un bloque try catch para evitar los métodos que podrían no implementarse? Si atrapas una excepción, ¿qué diablos se supone que debes hacer con eso?

No veo forma de probar si un método se implementa realmente sin llamarlo. Como llamarlo puede tener efectos secundarios, no puedo hacer todos mis controles por adelantado y luego ejecutar mi algoritmo. Tengo que ejecutar mi algoritmo, atrapar NotImplementedExceptions y la forma en que revierte mi aplicación a un estado razonable.

Es una locura. Enojado. Insano. Entonces la pregunta es: ¿Por qué existe la excepción NotImplementedException ?

Como un ataque preventivo, no quiero que nadie responda, “porque los diseñadores deben poner esto en el código autogenerado”. Esto es horrible Preferiría que el código generado automáticamente no se compile hasta que proporcione una implementación. Por ejemplo, la implementación generada automáticamente podría ser “throw NotImplementedException;” donde NotImplementedException no está definido!

¿Alguna vez alguien atrapó y manejó una NotImplementedException? ¿Alguna vez dejó una NotImplementedException en su código? Si es así, ¿representó esto una bomba de tiempo (es decir, la dejó accidentalmente allí), o una falla de diseño (el método no debe implementarse y nunca se llamará)?

También sospecho mucho de NotSupportedException … ¿No es compatible? ¿Que? Si no es compatible, ¿por qué es parte de su interfaz? ¿Puede alguien en Microsoft deletrear herencia indebida? Pero podría comenzar otra pregunta si no recibo demasiado abuso por esta.

Información adicional:

Esta es una lectura interesante sobre el tema.

Parece que hay un fuerte acuerdo con Brad Abrams en el sentido de que “NotImplementedException es para una funcionalidad que aún no se ha implementado, pero realmente debería (y lo será). Algo como lo que podría comenzar cuando se está creando una clase, obtener todos los métodos lanzando NotImplementedException, y luego eliminarlos con código real … ”

Los comentarios de Jared Parsons son muy débiles y probablemente deberían ser ignorados: NotImplementedException: lanza esta excepción cuando un tipo no implementa un método por cualquier otro motivo.

MSDN es aún más débil en el tema, simplemente indicando que, “La excepción que se lanza cuando un método u operación solicitada no se implementa”.

Hay una situación que me parece útil: TDD.

Escribo mis pruebas, luego creo stubs para que compilen las pruebas. Esos talones no hacen otra cosa que throw new NotImplementedException(); . De esta forma, las pruebas fallarán por defecto, sin importar qué. Si utilicé algún valor de retorno ficticio, podría generar falsos positivos. Ahora que todas las pruebas comstackn y fallan porque no hay implementación, abordo esos resúmenes.

Como nunca utilizo una NotImplementedException en ninguna otra situación, ninguna NotImplementedException pasará al código de lanzamiento, ya que siempre hará que falle alguna prueba.

No necesitas atraparlo por todos lados. Las buenas API documentan las excepciones lanzadas. Esos son los que debe buscar.

EDITAR: Escribí una regla FxCop para encontrarlos.

Este es el código:

 using System; using Microsoft.FxCop.Sdk; ///  /// An FxCop rule to ensure no  is /// left behind on production code. ///  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); } } } 

Y esta es la metadata de la regla:

    Do not raise NotImplementedException NotImplementedException should not be used in production code. http://stackoverflow.com/questions/410719/notimplementedexception-are-they-kidding-me Implement the method or property accessor. CriticalError  NonBreaking    

Para construir esto, necesitas:

  • referencia Microsoft.FxCop.Sdk.dll y Microsoft.Cci.dll

  • Coloque los metadatos en un archivo llamado DesignRules.xml y agréguelo como un recurso incrustado a su ensamblaje

  • Denomine a su conjunto Bevonn.CodeAnalysis . Si desea utilizar nombres diferentes para los archivos de metadatos o de ensamblaje, asegúrese de cambiar el segundo parámetro al constructor base de manera correspondiente.

Luego, simplemente agregue el ensamblaje resultante a sus reglas FxCop y elimine esas malditas excepciones de su precioso código. Hay algunos casos de esquina donde no se informará una NotImplementedException cuando se lanza, pero realmente creo que no tiene remedio si está escribiendo ese código cthulhian. Para usos normales, es decir, throw new NotImplementedException(); , funciona, y eso es todo lo que importa.

Está ahí para admitir un caso de uso bastante común, una API que funciona pero que está parcialmente completa. Digamos que quiero que los desarrolladores prueben y evalúen mi API – WashDishes() funciona, al menos en mi máquina, pero todavía no me he dado a la DryDishes() codificar DryDishes() , y mucho menos PutAwayDishes() . En lugar de fallar silenciosamente, o dar un mensaje de error críptico, puedo ser bastante claro acerca de por qué DryDishes() no funciona, no lo he implementado todavía.

Su excepción hermana NotSupportedException tiene sentido principalmente para los modelos de proveedor. Muchos lavavajillas tienen una función de secado, por lo que pertenecen a la interfaz, pero mi lavavajillas con descuento no es compatible. Puedo dejar que esto se conozca a través de NotSupportedException

Resumiré mis puntos de vista sobre esto en un solo lugar, ya que están dispersos en algunos comentarios:

  1. Utiliza NotImplementedException para indicar que un miembro de la interfaz aún no está implementado, pero lo será. Combina esto con pruebas unitarias automatizadas o pruebas de control de calidad para identificar características que aún deben implementarse.

  2. Una vez que se implementa la característica, elimina la NotImplementedException . Se escriben nuevas pruebas de unidad para la característica para garantizar que funcione correctamente.

  3. NotSupportedException generalmente se usa para proveedores que no admiten funciones que no tienen sentido para tipos específicos. En esos casos, los tipos específicos lanzan la excepción, los clientes los atrapan y los manejan según corresponda.

  4. La razón por la que NotImplementedException tanto NotImplementedException como NotSupportedException en el Framework es simple: las situaciones que los conducen son comunes, por lo que tiene sentido definirlas en el Framework, para que los desarrolladores no tengan que seguir redefiniéndolas. Además, facilita a los clientes saber qué excepción atrapar (especialmente en el contexto de una prueba unitaria). Si tiene que definir su propia excepción, tienen que descubrir qué excepción capturar, que es al menos un sumidero de tiempo contraproducente, y con frecuencia incorrecta.

¿Por qué existe la excepción NotImplementedException?

NotImplementedException es una excelente manera de decir que algo no está listo todavía. Por qué no está listo es una pregunta separada para los autores del método. En el código de producción es poco probable que capte esta excepción, pero si lo hizo, puede ver inmediatamente lo que sucedió y es mucho mejor que intentar averiguar por qué se llamaron los métodos, pero no pasó nada o incluso peor: recibir un resultado “temporal” y obtener efectos secundarios “divertidos”.

¿NotImplementedException es el equivalente de C # de la excepción UnsupportedOperationException de Java?

No, .NET tiene NotSupportedException

Tengo que ejecutar mi algoritmo, atrapar NotImplementedExceptions y la forma en que revierte mi aplicación a un estado razonable

Good API tiene documentación de métodos XML que describe posibles excepciones.

También sospecho mucho de NotSupportedException … ¿No es compatible? ¿Que? Si no es compatible, ¿por qué es parte de su interfaz?

Puede haber millones de razones Por ejemplo, puede introducir una nueva versión de API y no quiere / no puede admitir métodos antiguos. Una vez más, es mucho mejor ver una excepción descriptiva en lugar de profundizar en la documentación o depurar código de terceros.

El uso principal para una excepción NotImplementedException está en el código de código generado: ¡así no te olvides de implementarlo! Por ejemplo, Visual Studio implementará explícitamente los métodos / propiedades de una interfaz con el cuerpo arrojando una NotImplementedException.

Re NotImplementedException : esto sirve para algunos usos; proporciona una única excepción que (por ejemplo) puede bloquear las pruebas de su unidad para un trabajo incompleto. Pero también, realmente hace lo que dice: esto simplemente no está allí (todavía). Por ejemplo, “mono” arroja esto por todos lados para los métodos que existen en las librerías de MS, pero que aún no se han escrito.

Re NotSupportedException : no todo está disponible. Por ejemplo, muchas interfaces admiten un par “¿puedes hacer esto?” / “hacer esto”. Si el “¿puedes hacer esto?” devuelve falso, es perfectamente razonable que el “hacer esto” arroje NotSupportedException . Los ejemplos podrían ser IBindingList.SupportsSearching / IBindingList.Find() etc.

La mayoría de los desarrolladores de Microsoft están familiarizados con los patrones de diseño en los que una NotImplementedException es apropiada. Es bastante común en realidad.

Un buen ejemplo es un patrón compuesto , donde muchos objetos se pueden tratar como una sola instancia de un objeto. Un componente se utiliza como una clase abstracta base para clases de hojas heredadas (correctamente). Por ejemplo, una clase de Archivo y Directorio puede heredar de la misma clase base abstracta porque son tipos muy similares. De esta forma, pueden tratarse como un solo objeto (lo que tiene sentido cuando se piensa en qué son los archivos y directorios, en Unix, por ejemplo, todo es un archivo).

Entonces, en este ejemplo, habría un método GetFiles () para la clase Directory, sin embargo, la clase File no implementaría este método, porque no tiene sentido hacerlo. En cambio, obtienes una NotImplementedException, porque un archivo no tiene hijos como lo hace un directorio.

Tenga en cuenta que esto no está limitado a .NET: encontrará este patrón en muchos lenguajes y plataformas OO.

¿Por qué sientes la necesidad de atrapar todas las excepciones posibles? ¿Envuelve también todas las llamadas a métodos con catch (NullReferenceException ex) ?

Codigo NotImplementedException arroja NotImplementedException es un marcador de posición, si lo hace para liberarlo debería ser un error al igual que NullReferenceException .

Creo que hay muchas razones por las cuales MS agregó NotImplementedException al framework:

  • Como una conveniencia; dado que muchos desarrolladores lo necesitarán durante el desarrollo, ¿por qué todos deberían tener su propio diseño?
  • Para que las herramientas puedan confiar en su presencia; por ejemplo, el comando “Implementar interfaz” de Visual Studio genera stubs de métodos que lanzan NotImplementedException. Si no estuviera en el marco, esto no sería posible, o al menos bastante incómodo (por ejemplo, podría generar código que no comstack hasta que agregue su propia NotImplementedException)
  • Para fomentar una “práctica estándar” coherente

Frankodwyer piensa en NotImplementedException como una potencial bomba de tiempo. Diría que cualquier código inacabado es una bomba de tiempo, pero NotImplementedException es mucho más fácil de desarmar que las alternativas. Por ejemplo, podría hacer que su servidor de comstackción escanee el código fuente para todos los usos de esta clase y los informe como advertencias. Si realmente quiere prohibirlo, incluso podría agregar un enlace precompromiso a su sistema de control de origen que impida el registro de dicho código.

Claro, si tira su propia NotImplementedException, puede eliminarla de la construcción final para asegurarse de que no quedan bombas de tiempo. Pero esto solo funcionará si usa su propia implementación de manera consistente en todo el equipo, y debe asegurarse de no olvidarse de eliminarla antes de su lanzamiento. Además, es posible que no pueda eliminarlo; tal vez haya algunos usos aceptables, por ejemplo, en el código de prueba que no se envía a los clientes.

Realmente no hay razón para atrapar una NotImplementedException. Cuando se golpea, debería matar tu aplicación y hacerlo muy dolorosamente. La única forma de solucionarlo no es atrapándolo, sino cambiando su código fuente (ya sea implementando el método llamado o cambiando el código de llamada).

Dos razones:

  1. Los métodos se apagan durante el desarrollo y lanzan la excepción para recordar a los desarrolladores que la escritura de sus códigos no ha finalizado.

  2. Implementar una interfaz de subclase que, por diseño, no implementa uno o más métodos de la clase base o interfaz heredada. (Algunas interfaces son demasiado generales).

Esto me parece un potencial campo de minas. En el pasado remoto, una vez trabajé en un sistema de red heredado que había estado funcionando sin parar durante años y que se redujo en un día. Cuando rastreamos el problema, encontramos un código que claramente no se había terminado y que nunca podría haber funcionado, literalmente, como que el progtwigdor fue interrumpido durante la encoding. Era obvio que esta ruta de código particular nunca se había tomado antes.

La ley de Murphy dice que algo similar simplemente está pidiendo que suceda en el caso de NotImplementedException. Concedido en estos días de TDD, etc., debería ser recogido antes del lanzamiento, y al menos puedes codificar para esa excepción antes del lanzamiento, pero aún así.

Cuando se prueban, es difícil garantizar la cobertura de cada caso, y esto parece que hace su trabajo más difícil al hacer que los problemas de tiempo de comstackción sean los de tiempo de comstackción. (Creo que un tipo similar de “deuda técnica” viene con sistemas que dependen en gran medida de la “tipificación de pato”, aunque reconozco que son muy útiles).

Necesita esta excepción para la interoperabilidad COM. Es E_NOTIMPL . El blog vinculado también muestra otros motivos

Lanzar NotImplementedException es la forma más lógica para que el IDE genere código de comstackción. Al igual que cuando extiendes la interfaz y obtienes Visual Studio para que sea compatible contigo.

Si hiciste un poco de C ++ / COM, también existía allí, excepto que se lo conocía como E_NOTIMPL .

Hay un caso de uso válido para ello. Si está trabajando en un método particular de una interfaz, quiere que compile el código para que pueda depurarlo y probarlo. De acuerdo con su lógica, deberá eliminar el método de la interfaz y comentar el código de código no comstackdo. Este es un enfoque muy fundamentalista y si bien tiene sus méritos, no todos o deberían adherirse a eso. Además, la mayoría de las veces quieres que la interfaz esté completa.

Tener una excepción NotImplementedException identifica bien qué métodos no están listos aún, al final del día es tan fácil como presionar Ctrl+Shift+F para encontrarlos a todos, también estoy seguro de que las herramientas de análisis de código estático lo recogerán también.

No está destinado a enviar código que tenga la excepción NotImplementedException . Si crees que al no usarlo puedes mejorar tu código, avanzar, pero hay cosas más productivas que puedes hacer para mejorar la calidad de la fuente.

NotImplementedException

La excepción se produce cuando un método u operación solicitada no se implementa.

Al hacer de esto una excepción única definida en el núcleo .NET, es más fácil encontrarlos y erradicarlos. Si cada desarrollador debe crear su propia ACME.EmaNymton.NotImplementedException sería más difícil encontrarlos a todos.

NotSupportedException

La excepción se produce cuando un método invocado no es compatible.

Por ejemplo, cuando hay un bash de leer, buscar o escribir en una secuencia que no admite la funcionalidad invocada.

Por ejemplo, los iteradores generados (usando la palabra clave yield ) son: un IEnumerator , pero el método NotSupportedException arroja NotSupportedException .

Desde ECMA-335, la especificación CLI, específicamente la CLI Library Types, System.NotImplementedException, sección de observaciones:

“Varios tipos y construcciones, especificados en otras partes de este Estándar, no son necesarios para las implementaciones de CLI que se ajustan solo al Perfil de kernel. Por ejemplo, el conjunto de características de punto flotante consiste en los tipos de datos de coma flotante Sistema.Solo y System.Doble. Si el soporte para estos se omite de una implementación, cualquier bash de referenciar una firma que incluya los tipos de datos de coma flotante dará como resultado una excepción de tipo System.NotImplementedException “.

Por lo tanto, la excepción está destinada a implementaciones que implementan solo perfiles de conformidad mínimos. El perfil mínimo requerido es el Kernel Profile (consulte la cuarta edición de ECMA-335 – Partition IV, sección 3), que incluye el BCL, por lo que la excepción se incluye en la “API principal” y no en otra ubicación.

Usar la excepción para designar métodos tropezados, o para métodos generados por el diseñador que carecen de implementación es no entender el propósito de la excepción.

En cuanto a por qué esta información NO está incluida en la documentación de MSDN para la implementación de MS de la CLI me supera.

No puedo responder por NotImplementedException (en general estoy de acuerdo con su opinión) pero he usado NotSupportedException extensamente en la biblioteca principal que usamos en el trabajo. El DatabaseController, por ejemplo, le permite crear una base de datos de cualquier tipo compatible y luego usar la clase DatabaseController en el rest del código sin preocuparse demasiado por el tipo de base de datos que se encuentra debajo. Bastante básico, ¿verdad? Donde NotSupportedException es útil (y donde habría utilizado mi propia implementación si aún no existiera) son dos instancias principales:

1) Migrar una aplicación a una base de datos diferente A menudo se argumenta que esto rara vez, o nunca, sucede o es necesario. Bullsh * t. Saca más.

2) Misma base de datos, controlador diferente El ejemplo más reciente de esto fue cuando un cliente que usa una aplicación respaldada por Access se actualizó de WinXP a Win7 x64. Al no ser un controlador JET de 64 bits, su técnico de TI instaló AccessDatabaseEngine en su lugar. Cuando nuestra aplicación se bloqueó, pudimos ver fácilmente desde el registro que se había bloqueado DB.Connect con NotSupportedException, que pudimos abordar rápidamente. Otro ejemplo reciente fue uno de nuestros progtwigdores tratando de usar transacciones en una base de datos de Access. Aunque Access admite transacciones, nuestra biblioteca no admite transacciones de acceso (por motivos que están fuera del scope de este artículo). NotSupportedException, ¡es tu momento de brillar!

3) Funciones genéricas No puedo pensar en un ejemplo conciso de “experiencia” aquí, pero si piensas en algo así como una función que agrega un archivo adjunto a un correo electrónico, quieres que sea capaz de tomar algunos archivos comunes como archivos JPEG, cualquier cosa derivada de varias clases de flujo, y prácticamente cualquier cosa que tenga un método “.ToString”. Para la última parte, ciertamente no puedes dar cuenta de todos los tipos posibles, así que lo haces genérico. Cuando un usuario pasa OurCrazyDataTypeForContainingProprietarySpreadsheetData, utilice la reflexión para probar la presencia de un método ToString y devuelva NotSupportedException para indicar la falta de compatibilidad con dichos tipos de datos que no son compatibles con ToString.

NotSupportedException no es de ninguna manera una característica crucial, pero es algo que utilizo mucho más a medida que trabajo en proyectos más grandes.

Digamos que tienes este método en tu código de producción

 public void DoSomething() 

¿Cuál tomarías si quisieras dejarlo más tarde para terminar?

 public void DoSomething() { } 

o

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

Ciertamente tomaría el segundo. Junto con Elmah o cualquier mecanismo de registro de errores que tenga (implementado como un aspecto en toda su aplicación). Junto con el filtro de registro / excepción para activar la notificación por correo electrónico de errores críticos cuando uno es atrapado.

El argumento de que NotImplementedException == inacabado tampoco es correcto. (1) La captura de métodos no implementados debe dejarse en pruebas unitarias / pruebas de integración. If you have 100% coverage (which you should now do, with so many many mock/stub/code generation tools) with no NotImplementedException, what are your worries? (2) Code generation. Plain simple. Again, if I generate the code, and only use half of the generated code, why wouldn’t I have NotImplementedException in the rest of the generated stub?

It’s like saying code shouldn’t compile unless every nullable input should be checked/handled for null. (AKA the trillion dollar mistake, if not more). Language should be flexible, while tests/contracts should be solid.

Rarely I do use it for interface fixing. Assume that you’ve an interface that you need to comply but certain method will be never called by anyone, so just stick a NotImplementedException and if someone calls it they will know they are doing something wrong.

NotImplementedException is thrown for some method of .NET (see the parser C# in Code DOM which is not implemented, but the method exist !) You can verify with this method Microsoft.CSharp.CSharpCodeProvider.Parse

They are both hacks for two common problems.

NotImplementedException is a workaround for developers who are architecture astronauts and like to write down the API first, code later. Obviously, since this is not a incremental process, you can’t implement all at once and therefore you want to pretend you are semi-done by throwing NotImplementedException.

NotSupportedException is a hack around the limitation of the type systems like those found in C# and Java. In these type systems, you say that a Rectangle ‘is a’ Shape iff Rectangle inherits all of Shapes characteristics (incl. member functions + variables). However, in practice, this is not true. For example, a Square is a Rectangle, but a Square is a restriction of a Rectangle, not a generalization.

So when you want to inherit and restrict the behavior of the parent class, you throw NotSupported on methods which do not make sense for the restriction.

What about prototypes or unfinished projects?

I don’t think this is a really bad idea to use an exception (although I use a messagebox in that case).

Well, I somewhat agree. If an interface has been made in such a way that not all class can implement all bits of it, it should’ve been broken down in my opinion.

If IList can or cannot be modified, it should’ve been broken down into two, one for the unmodifiable part (getters, lookup, etc.), and one for the modifiable part (setters, add, remove, etc.).

I have a few NotImplementedExceptions in my code. Often times it comes from part of an interface or abstract class. Some methods I feel I may need in the future, they make sense as being part of the class, but I just don’t want to take the time to add unless I actually need it. For example, I have an interface for all the individual kinds of stats in my game. One of those kinds are a ModStat, which is the sum of the base stat plus all the modifiers (ie weapons, armor, spells). My stat interface has an OnChanged event, but my ModStat works by calculating the sum of all stats it references each time it is called. So instead of having the overhead of a ton of ModStat.OnChange events being raised every time a stat changes, I just have a NotImplementedException thrown if anyone tries to add/remove a listener to OnChange.

.NET languages are all about productivity, so why spend your time coding something you won’t even use?

Here is one example: In Java, whenever you implement the interface Iterator , you have to override the obvious methods hasNext() and next() , but there is also delete() . In 99% of the usecases I have I do not need this, so I just throw a NotImplementedException . This is much better than silently doing nothing.

The NotImplementedException exists only to facilitate development. Imagine you start implementing an interface. You’d like to be able to at least build when you are done implementing one method, before moving to the next. Stubbing the NotImplemented methods with NotImplementedExceptions is a great way of living unfinished code that is super easy to spot later. Otherwise you would run the risk of quickly implementing something that you might forget to fix.

If you don’t want to use it then just ignore it. If you have a block of code whose success depends on every piece of it succeeding, but it might fail in between, then your only option is to catch the base Exception and roll back what needs to be rolled back. Forget NotImplementedException . There could be tons of exceptions thrown, like MyRandomException and GtfoException and OmgLolException . After you originally write the code I could come by and throw ANOTHER exception type from the API you’re calling. One that didn’t exist when you wrote your code. Handle the ones you know how to handle and rollback for any others ie, catch(Exception) . It’s pretty simple, I think… I find it comes in handy too. Especially when you’re trying fancy things with the language/framework that occasionally force things upon you.

One example I have is serialization. I have added properties in my .NET library that don’t exist in the database (for example, convenient wrappers over existing “dumb” properties, like a FullName property that combines FirstName , MiddleName , and LastName ). Then I want to serialize these data types to XML to send them over the wire (for example, from an ASP.NET application to JavaScript), but the serialization framework only serializes public properties with both get and set accessors. I don’t want you to be able to set FullName because then I’d have to parse it out and there might be some unforeseen format that I wrongly parse and data integrity goes out the window. It’s easier to just use the underlying properties for that, but since the language and API require me to have a set accessor, I’ll throw a NotImplementedException (I wasn’t aware of NotSupportedException until I read this thread, but either one works) so that if some programmer down the road does try to set FullName he’ll encounter the exception during testing and realize his mistake.