valid - summary returns c#
¿Pros/contras de los diferentes métodos para probar las condiciones previas? (2)
El primer método es apropiado para probar una condición nula que nunca debería existir. Es decir, utilícelo durante el desarrollo para asegurarse de que no se establezca inesperadamente en nulo. Dado que no hace ningún manejo de errores, esto no es apropiado para manejar condiciones nulas en su producto lanzado.
Yo diría que las versiones 2 y 3 son similares, ya que no manejan el problema de ninguna manera.
En general, si existe la posibilidad de que la variable pueda ser nula en el producto final, la última versión es la que se debe utilizar. Usted podría hacer un manejo especial allí, o simplemente generar una excepción como lo ha hecho.
Desde lo alto de mi cabeza, puedo pensar en 4 formas de verificar los argumentos nulos:
Debug.Assert(context != null);
Contract.Assert(context != null);
Contract.Requires(context != null);
if (context == null) throw new ArgumentNullException("context");
Siempre he usado el último método, pero acabo de ver un fragmento de código que usaba Contract.Requires
. Contract.Requires
, con los que no estoy familiarizado. ¿Cuáles son las ventajas / desventajas de cada método? ¿Hay otras formas?
En VS2010 w / Resharper,
-
Contract.Assert
me advierte que la expresión siempre es verdadera (como sabe, no estoy muy segura ... ¿no puede HttpContext ser nulo?), -
Contract.Requires
se desvanece y me dice que el compilador no invocará el método (supongo que debido a la razón anterior, nunca será nulo), y - si cambio el último método a
context != null
todo el código siguiente se desvanece y me dice que el código es heurísticamente inalcanzable.
Entonces, parece que los últimos 3 métodos tienen algún tipo de inteligencia integrada en el comprobador estático de VS, y Debug.Assert
es simplemente tonto.
IHttpHandler.ProcessRequest que hay un contrato aplicado a la interfaz IHttpHandler.ProcessRequest que requiere ese contexto! = Nulo. Los contratos de interfaz son heredados por sus implementadores, por lo que no es necesario repetir los requisitos. De hecho, no se le permite agregar declaraciones de Requisitos adicionales, ya que está limitado a los requisitos asociados con el contrato de interfaz.
Creo que es importante hacer una distinción entre especificar una obligación contractual en lugar de simplemente realizar una comprobación nula. Puede implementar una comprobación nula y lanzar una excepción en el tiempo de ejecución, como una forma de informar al desarrollador de que están utilizando su API correctamente. Una expresión de Contrato, por otro lado, es realmente una forma de metadatos, que puede ser interpretada por el reescritor del contrato (para introducir las excepciones de tiempo de ejecución que se implementaron previamente manualmente), pero también por el analizador estático, que puede usarlas para razonar. sobre la corrección estática de su aplicación.
Dicho esto, si está trabajando en un entorno en el que está utilizando activamente Contratos de código y análisis estático, definitivamente es preferible poner las aserciones en forma de Contrato, para aprovechar el análisis estático. Incluso si no está utilizando el análisis estático, puede dejar la puerta abierta para beneficios posteriores mediante el uso de contratos. Lo principal a tener en cuenta es si ha configurado sus proyectos para realizar la reescritura, ya que de lo contrario los contratos no darán lugar a excepciones de tiempo de ejecución como podría esperar.
Para detallar lo que han dicho los comentaristas, la diferencia entre afirmar, asumir y requiere es:
- Una expresión Contract.Assert se transforma en una aserción por parte del reescritor del contrato y el analizador estático intenta probar la expresión basándose en su evidencia existente. Si no puede probarse, recibirá una advertencia de análisis estático.
- El redactor de contratos ignora la expresión de un Contrato (en lo que sé), pero el analizador estático lo interpreta como una nueva pieza de evidencia que puede tener en cuenta en su análisis estático. Contrato. Asumir se utiliza para ''llenar los huecos'' en el análisis estático, ya sea donde carece de la sofisticación para hacer las inferencias necesarias o cuando se interopera con el código que no ha sido decorado con Contratos, por lo que puede asumir, por ejemplo. , que una llamada de función particular devuelve un resultado no nulo.
- Contrato. Los requisitos son condiciones que siempre deben cumplirse cuando se llama a su método. Pueden ser restricciones en los parámetros del método (que son los más típicos) y también pueden ser restricciones en los estados visibles del objeto (por ejemplo, puede permitir que solo se llame al método si Initialized es True). Las restricciones empujan a los usuarios de su clase a verificar Inicializado cuando usan el objeto (y presumiblemente manejan el error si no lo es) o crear sus propias restricciones y / o invariantes de clase para aclarar que la Inicialización, efectivamente, ha ocurrido.