2011-06-17 11 views
13

estoy escribiendo atributo de seguridad personalizada y consiguió el comportamiento del compilador extraño ... Cuando estoy usando el atributo en el mismo archivo, valores de los parámetros por defecto funciona bien:¿Es esto un error de parámetros opcionales del compilador C# 4.0?

using System.Security.Permissions; 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute { 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

[Foo] class Program { 
    static void Main(string[] args) { } 
} 

Pero cuando estoy separando el código anteriormente en dos archivos como archivos que - 1:

using System.Security.Permissions; 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute { 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

y el archivo 2:

[Foo] class Program { 
    static void Main(string[] args) { } 
} 

que tengo un error del compilador:

Error: 'FooAttribute' does not contain a constructor that takes 0 arguments

Esto ocurre sólo con los CodeAccessSecurityAttribute herederos, se ve muy extraño ...

+2

¿Cuál es la relación entre FooAttribute, en la fuente, y DebugCallTraceAttribute, en el mensaje de error? –

+2

¿Hay alguna razón para 'SecurityAttribute' en el primer fragmento y' CodeAccessSecurityAttribute' en el segundo? Parece que esto debería ser igual para un caso de prueba mínimo válido. (Por ejemplo, ¿está relacionado con este cambio o está en dos archivos o en ambos?) –

+0

lo siento, son las 3 a.m. en Moscú, se han corregido todos los errores en los fragmentos – ControlFlow

Respuesta

13

por lo que no tienen una respuesta exacta, pero lo tomé como lo que pude mirar en él. Creo que entiendo por qué ocurre cuando se hereda de CodeAccessSecurityAttribute y no SecurityAttribute. Si nos fijamos en el IL generado al aplicar el atributo Foo cuando se hereda de CodeAccessSecurityAttribute se ve así:

.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}} 

Cuándo Foo hereda de SecurityAttribute se se parece a esto:

.custom instance void ConsoleApplication1.FooAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction) = (01 00 02 00 00 00 00 00) 

Claramente el CodeAccessSecurityAttribute cambia drásticamente la IL genera aplicando el atributo.

En cuanto a la IL más si cambiamos la declaración Foo ser como la siguiente manera

[Foo(SecurityAction.Demand)] 

obtenemos la IL siguiente:

.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}} 

Es el mismo que era cuando no especifica el parámetro opcional. Además podemos hacer que el error no sólo mediante la división del atributo y la clase Program en archivos separados que podemos hacer que mediante la reordenación de los archivos de la clase como esta:

[Foo] 
class Program 
{ 

    static void Main(string[] args) {} 


} 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute 
{ 
    public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
    public override System.Security.IPermission CreatePermission() { return null; } 
} 

Aún más interesante si hacemos lo siguiente con la clase Other y Other2 dan el error pero Program no. Sólo las clases que se presentan ante Foo en el archivo tendrán el error

[Foo] 
class Other 
{ 

} 

[Foo] 
class Other2 
{ 
} 

[System.Serializable] 
sealed class FooAttribute : CodeAccessSecurityAttribute 
{ 
     public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { } 
     public override System.Security.IPermission CreatePermission() { return null; }  } 

[Foo] 
class Program 
{ 

    static void Main(string[] args) {} 
} 

Lo que esto me dice es que hay un problema en alguna parte del proceso de construcción. No sé lo suficiente sobre cómo funciona Code Access Security para saber cuál es el problema exacto. Tiene que haber una parte del proceso que examine CodeAccessSecurityAttributes y haga algo al intentar aplicar SecurityAction al código. Supongo que construye algún tipo de metadato para el ensamblaje. Debe hacer esto de alguna manera ordenada para que no vea el parámetro opcional hasta después de que ya haya pasado la clase Program. Luego debe usar esos metadatos de alguna manera durante el proceso de compilación y es ahí donde está viendo el error. Para más detalles, tendremos que esperar que alguien que conozca el compilador, es decir, Eric, pueda arrojar algo de luz sobre él. Lo enviaría en connect.microsoft.com como uno de los comentarios sugeridos, ya que parece un error causado por el orden en que se atraviesan las cosas.

+1

+1 de mí para un buen análisis. – Jehof

+0

¡Si solo ** todos los informes de errores fueran tan bien investigados y escritos! –

Cuestiones relacionadas