¿Se garantiza que los contratos de código se evalúen antes de llamar a los constructores encadenados?

Antes de comenzar a usar los Contratos de Código, a veces me encontraba con problemas relacionados con la validación de parámetros cuando utilizaba el encadenamiento de constructores.

Esto es más fácil de explicar con un ejemplo (creado):

class Test
{
    public Test(int i)
    {
        if (i == 0)
            throw new ArgumentOutOfRangeException("i", i, "i can't be 0");
    }

    public Test(string s): this(int.Parse(s))
    {
        if (s == null)
            throw new ArgumentNullException("s");
    }
}

Quiero elTest(string) constructor para encadenar elTest(int) constructor, y para ello utilizoint.Parse().

Por supuesto,int.Parse() no le gusta tener un argumento nulo, así que sis es nulo que tirará antes de que alcance las líneas de validación:

if (s == null)
    throw new ArgumentNullException("s");

Lo que hace inútil ese cheque.

¿Cómo arreglar eso? Bueno, a veces solía hacer esto:

class Test
{
    public Test(int i)
    {
        if (i == 0)
            throw new ArgumentOutOfRangeException("i", i, "i can't be 0");
    }

    public Test(string s): this(convertArg(s))
    {
    }

    static int convertArg(string s)
    {
        if (s == null)
            throw new ArgumentNullException("s");

        return int.Parse(s);
    }
}

Eso es un poco incómodo, y el seguimiento de la pila no es ideal cuando falla, pero funciona.

Ahora, a lo largo de los contratos de código, comencé a usarlos:

class Test
{
    public Test(int i)
    {
        Contract.Requires(i != 0);
    }

    public Test(string s): this(convertArg(s))
    {
    }

    static int convertArg(string s)
    {
        Contract.Requires(s != null);
        return int.Parse(s);
    }
}

Todo bien y bien. Funciona bien. Pero luego descubro que puedo hacer esto:

class Test
{
    public Test(int i)
    {
        Contract.Requires(i != 0);
    }

    public Test(string s): this(int.Parse(s))
    {
        // This line is executed before this(int.Parse(s))
        Contract.Requires(s != null);
    }
}

Y luego si lo hagovar test = new Test(null), laContract.Requires(s != null) es ejecutadoantes de this(int.Parse(s)). Esto significa que puedo acabar con elconvertArg() prueba en total!

Así que, a mis preguntas reales:

¿Está este comportamiento documentado en alguna parte?¿Puedo confiar en este comportamiento al escribir contratos de código para constructores encadenados como este?¿Hay alguna otra forma en que debería estar acercándome a esto?

Respuestas a la pregunta(1)

Su respuesta a la pregunta