2011-01-21 21 views

Respuesta

60

Imagine que tiene un método como este:

bool ContainsAnX(string s) 
{ 
    return s.Contains("X"); 
} 

Ahora, este método siempre se producirá un error si pasa null a ella, por lo que desea asegurarse de que esto nunca sucede. Esto es para lo que Contract.Requires es. Establece un precondición para el método, que debe ser verdadero para que el método se ejecute correctamente. En este caso tendríamos:

bool ContainsAnX(string s) 
{ 
    Contract.Requires(s != null); 

    return s.Contains("X"); 
} 

(Nota: Requires y Ensures siempre debe estar en el inicio de un método, ya que son la información sobre el método en su conjunto Assume se utiliza en el propio código. , ya que es información sobre ese punto en el código.)

Ahora, en su código que llama al método "ContainsAnX", debe asegurarse de que la cadena no sea nula. Su método podría tener este aspecto:

void DoSomething() 
{ 
    var example = "hello world"; 

    if (ContainsAnX(example)) 
     Console.WriteLine("The string contains an 'X'."); 
    else 
     Console.WriteLine("The string does not contain an 'X'."); 
} 

Esto funciona bien, y el de electricidad estática puede probar que example no es nulo.

Sin embargo, es posible que llame a bibliotecas externas, que no tienen información sobre los valores que devuelven (es decir, no usan Contratos de código). Vamos a cambiar el ejemplo:

void DoSomething() 
{ 
    var example = OtherLibrary.FetchString(); 

    if (ContainsAnX(example)) 
     Console.WriteLine("The string contains an 'X'."); 
    else 
     Console.WriteLine("The string does not contain an 'X'."); 
} 

Si el OtherLibrary no utiliza Code Contracts, el corrector estática se quejan de que example podría ser nulo.

Tal vez su documentación para la biblioteca dice que el método nunca devolverá nulo (o debe nunca!). En este caso, sabemos más que el de electricidad estática hace, así que podemos decir que a Assume que la variable nunca será nulo:

void DoSomething() 
{ 
    var example = OtherLibrary.FetchString(); 

    Contract.Assume(example != null); 

    if (ContainsAnX(example)) 
     Console.WriteLine("The string contains an 'X'."); 
    else 
     Console.WriteLine("The string does not contain an 'X'."); 
} 

Ahora bien, esto va a estar bien con el de electricidad estática. Si tiene contratos de tiempo de ejecución habilitados, Assume también se comprobará en tiempo de ejecución.

Otro caso en el que podría necesitar Asumir es cuando sus condiciones previas son muy complejas y el verificador estático está teniendo dificultades para probarlas.En este caso, puede darle un pequeño empujón para ayudarlo :)

En términos de comportamiento en el tiempo de ejecución, no habrá mucha diferencia entre usar Assume y Requires. Sin embargo, los resultados con el verificador estático serán muy diferentes. El significado de cada uno es diferente, así, en términos de quién es responsable del error en caso de fallo:

  • Requiere significa que el código que llama a este método debe asegurar la condición se cumple.
  • Suponer significa que este método es una suposición que siempre debería ser cierta.
+0

¡Muy buena explicación! Pero una pregunta. ¿Qué quieres decir con "inspector estático"? Estoy usando la edición VS Professional. – user137348

+1

El comprobador estático es un programa que intenta verificar que todos los contratos son verdaderos en tiempo de compilación. Desafortunadamente, solo está disponible con la edición VS2010 Premium o Ultimate en este momento. – porges

+1

El comprobador estático ahora está disponible para todos los niveles de Visual Studio (excepto Express, por supuesto). – porges

2

Sólo se diferencia en tiempo de diseño/análisis en tiempo-estática

Contract.Assume: "Encarga herramientas de análisis de código para suponer que la condición especificada es verdadera, incluso si no se puede probar de forma estática a siempre será verdadero " y: En tiempo de ejecución, usar este método es equivalente a usar el método Assert (Boolean).

Contract.Requires garantizará que el predicado dado sea verdadero y los analizadores de código estáticos puedan generar un error si no pueden 'probar' que no es el caso. En contrato. Supongamos que el analizador estático continuará/emitirá una advertencia/lo que sea que la herramienta decida.

+0

¿Cuál es el que debería usar en mi código? – user137348

+1

Suponer y Requiere hacer cosas fundamentalmente diferentes. – porges

0

Según official documentation: páginas 7 (condiciones previas) y 11 (se supone).

Requiere:

  • es una condición previa ("condiciones previas se extressed utilizando Contract.Requires");
  • Como una condición previa se ejecutará en la invocación del método;

Asume:

  • No es un requisito, no una condición posterior, no un invariante;
  • Se ejecuta en el punto donde se especifica;
  • p. 11 "Existe en una construcción solo cuando se define el símbolo de contrato completo o el símbolo DEBUG";
Cuestiones relacionadas