Conjunto de reglas de análisis de código Reglas de directrices de diseño básicas de Microsoft
Puede utilizar el conjunto Reglas de directrices de diseño básicas de Microsoft para centrarse en facilitar la comprensión y el uso del código. Se recomienda incluir este conjunto de reglas si el proyecto incluye código de bibliotecas o si desea exigir procedimientos recomendados para el código que es fácil de mantener.
El conjunto Reglas de directrices de diseño básicas incluye todas las reglas del conjunto Reglas mínimas recomendadas de Microsoft. Para obtener una lista de las reglas mínimas, vea Conjunto de reglas de análisis de código Reglas mínimas recomendadas de Microsoft.
En la tabla siguiente se describen todas las reglas del conjunto Reglas de directrices de diseño básicas de Microsoft.
Regla |
Descripción |
---|---|
Cuando se llama a un miembro estático de un tipo genérico, se debe especificar el argumento de tipo correspondiente a ese tipo. Cuando se llama a un miembro de instancia genérico que no admite la interferencia, se debe especificar el argumento de tipo para el miembro. En estos dos casos, la sintaxis para especificar el argumento de tipo es diferente y resulta fácil confundirse. |
|
System.Collections.Generic.List < (De <(T>)>) es una colección genérica diseñada para el rendimiento, no para la herencia. Por consiguiente, List no contiene ningún miembro virtual. En su lugar, deben exponerse las colecciones genéricas diseñadas para herencia. |
|
CA1003: Utilizar instancias genéricas de controlador de eventos |
Un tipo contiene un delegado que devuelve void, su firma contiene dos parámetros (el primero es un objeto y el segundo es un tipo asignable a EventArgs), y el ensamblado que lo contiene está dirigido a .NET Framework 2.0. |
CA1004: Los métodos genéricos deben proporcionar un parámetro de tipo |
La inferencia es el modo en que se determina el argumento de tipo de un método genérico partiendo del tipo de argumento pasado al método, en lugar de especificar directamente el argumento de tipo. Para habilitar la inferencia, la firma de parámetro de un método genérico debe incluir un parámetro del mismo tipo que el parámetro type del método. En este caso, no es necesario especificar el argumento de tipo. Cuando se utiliza la inferencia para todos los parámetros de tipo, la sintaxis para llamar a los métodos de instancia genéricos y no genéricos es la misma; esto simplifica la capacidad de uso de los métodos genéricos. |
Cuantos más parámetros type contenga un tipo genérico, más difícil resulta saber y recordar qué representa cada uno de ellos. Normalmente, esto resulta evidente con los parámetros de tipo, como en List <T>, y en algunos casos con dos parámetros de tipo, como en Dictionary<TKey, TValue>. Sin embargo, si hay más de dos parámetros de tipo, la dificultad se vuelve demasiado grande para la mayoría de los usuarios. |
|
Un argumento de tipo anidado es un argumento de tipo que también es un tipo genérico. Para llamar a un miembro cuya firma contenga un argumento de tipo anidado, el usuario debe crear instancias de un tipo genérico y pasar este tipo al constructor de un segundo tipo genérico. El procedimiento y la sintaxis necesarios para ello son complejos, por lo que es preferible evitarlo. |
|
Un método visible externamente contiene un parámetro de referencia de tipo System.Object. El uso de un método genérico permite pasar al método todos los tipos, en función de las restricciones, sin convertirlos antes al tipo del parámetro de referencia. |
|
El valor predeterminado de una enumeración no inicializada, igual que otros tipos de valor, es cero. Una enumeración con atributo y sin marcadores debería definir un miembro con el valor de cero de modo que el valor predeterminado sea un valor válido de la enumeración. Si una enumeración a la que se le haya aplicado el atributo FlagsAttribute define un miembro con valor cero, su nombre debe ser "None" para indicar que no se han establecido valores en la enumeración. |
|
CA1010: Las colecciones deben implementar la interfaz genérica |
Para ampliar la utilidad de una colección, implemente una de las interfaces de colección genéricas. Entonces podrá utilizar la colección para rellenar tipos de colecciones genéricas. |
Cuando en una declaración de método se especifica un tipo base como parámetro, cualquier tipo derivado del tipo base puede pasarse al método como el argumento correspondiente. Si la funcionalidad adicional proporcionada por el tipo de parámetro derivado no resulta necesaria, el uso del tipo base permite que el método se utilice más ampliamente. |
|
CA1012: Los tipos abstractos no deberían tener constructores |
Los tipos derivados pueden llamar sólo a los constructores de tipos abstractos. Puesto que los constructores públicos crean instancias de un tipo y no se pueden crear instancias de un tipo abstracto, no es correcto diseñar un tipo abstracto con un constructor público. |
CA1013: El operador de sobrecarga es igual que la suma y resta de sobrecarga |
Un tipo público o protegido implementa los operadores de suma o resta sin implementar el operador de igualdad. |
La Common Language Specification (CLS) define las restricciones de nomenclatura, los tipos de datos y las reglas a las que los ensamblados deben ajustarse si se van a utilizar los lenguajes de programación. Los procedimientos de diseño establecen que todos los ensamblados deben indicar explícitamente la conformidad con CLS mediante el atributo CLSCompliantAttribute. Si este atributo no está presente en un ensamblado, el ensamblado no es conforme. |
|
ComVisibleAttribute determina cómo obtienen acceso los clientes COM al código administrado. Los procedimientos de diseño recomendados dictan que los ensamblados indican explícitamente la visibilidad COM. La visibilidad COM se puede establecer para un ensamblado completo y, a continuación, se puede invalidar para los tipos individuales y los miembros de tipo. Si este atributo no está presente, el contenido del ensamblado es visible para los clientes COM. |
|
Al definir un atributo personalizado, márquelo utilizando AttributeUsageAttribute para indicar dónde se puede aplicar el atributo personalizado en el código fuente. El significado de un atributo y el uso que se le va a dar determinará sus ubicaciones válidas en código. |
|
CA1019: Definir descriptores de acceso para los argumentos de atributo |
Los atributos pueden definir argumentos obligatorios que deben especificarse al aplicar el atributo a un destino. Éstos también se denominan argumentos posicionales porque se proporcionan para atribuir constructores como parámetros posicionales. Para cada argumento obligatorio, el atributo debe proporcionar también una propiedad de sólo lectura correspondiente de modo que el valor del argumento se pueda recuperar en tiempo de ejecución. Los atributos también pueden definir argumentos opcionales, que también se denominan argumentos con nombre. Estos argumentos se proporcionan para atribuir constructores por nombre y deben tener una propiedad de lectura/escritura correspondiente. |
Los indizadores (es decir, las propiedades indizadas) deben utilizar un índice único. Los indizadores multidimensionales pueden reducir de forma significativa la utilidad de la biblioteca. |
|
Un método público o protegido tiene un nombre que comienza por "Get", no toma ningún parámetro y devuelve un valor que no es una matriz. El método podría ser un buen candidato para convertirse en propiedad. |
|
CA1025: Reemplaza argumentos repetitivos con una matriz de parámetros |
Utilice una matriz de parámetros en lugar de argumentos repetidos si no conoce el número exacto de argumentos y si los argumentos de variable son del mismo tipo o pueden pasarse como si fueran del mismo tipo. |
Los métodos que utilizan parámetros predeterminados están permitidos en Common Language Specification (CLS); sin embargo, la CLS permite que los compiladores omitan los valores asignados a estos parámetros. Para seguir utilizando el comportamiento que desea en los lenguajes de programación, los métodos que utilizan parámetros predeterminados deberían reemplazarse con sobrecargas de métodos que proporcionen los parámetros predeterminados. |
|
Una enumeración es un tipo de valor que define un conjunto de constantes con nombre relacionadas. Aplique FlagsAttribute a una enumeración cuando se pueda combinar con sentido sus constantes con nombre. |
|
CA1028: El almacenamiento de la enumeración debe ser de tipo Int32 |
Una enumeración es un tipo de valor que define un conjunto de constantes con nombre relacionadas. De manera predeterminada, el tipo de datos System.Int32 se utiliza para almacenar el valor constante. Aunque puede cambiar este tipo subyacente, no es necesario ni se recomienda en la mayoría de los escenarios. |
Esta regla detecta métodos que tienen nombres que normalmente se utilizarían para eventos. Si se llama a un método en respuesta a un cambio de estado claramente definido, un controlador de eventos debe invocar al método. Los objetos que llaman al método deben provocar eventos en lugar de llamar directamente al método. |
|
No se deben capturar excepciones generales. Detecte una excepción más específica, o vuelva a producir una excepción general como la última instrucción del bloque Catch. |
|
El error al proporcionar el conjunto completo de constructores puede dificultar el control correcto de las excepciones. |
|
Los tipos anidados son tipos declarados en el ámbito de otro tipo. Los tipos anidados son útiles para encapsular los detalles de la implementación privada del tipo contenido. Los tipos anidados, utilizados para este propósito, no deben ser visibles externamente. |
|
CA1035: Las implementaciones de ICollection tienen miembros fuertemente tipados |
Esta regla requiere implementaciones de ICollection para proporcionar miembros fuertemente tipados para que los usuarios no necesiten convertir los argumentos en el tipo Object cuando utilicen la funcionalidad proporcionada por la interfaz. Esta regla supone que el tipo que implementa ICollection lo hace para administrar una colección de instancias de un tipo que es más fuerte que Object. |
Un tipo público o protegido implementa la interfaz System.IComparable. No reemplaza Object.Equals ni sobrecarga al operador específico del lenguaje para la igualdad, desigualdad, menor que o mayor que. |
|
Esta regla requiere implementaciones de IEnumerator para proporcionar una versión fuertemente tipada de la propiedad Current para que los usuarios no tengan que convertir el valor devuelto en un tipo inflexible cuando utilicen la funcionalidad proporcionada por la interfaz. |
|
Esta regla requiere que las implementaciones de IList proporcionen miembros fuertemente tipados para que los usuarios no necesiten convertir los argumentos en el tipo System.Object cuando utilicen la funcionalidad proporcionada por la interfaz. |
|
Un tipo o miembro se marca con un atributo System.ObsoleteAttribute para el que no se ha especificado su propiedad ObsoleteAttribute.Message. Cuando se compila un tipo o miembro marcado con ObsoleteAttribute, se muestra la propiedad Message del atributo proporcionando al usuario información relacionada con el tipo o miembro obsoleto. |
|
CA1043: Utilizar argumento integral o de cadena para los indizadores |
Los indizadores (es decir, las propiedades indizadas) deben utilizar tipos enteros o de cadena para el índice. Estos tipos se utilizan normalmente para indizar las estructuras de datos y aumentan la utilidad de la biblioteca. El uso del tipo Object debería limitarse a los casos en los que el tipo entero o de cadena no se puede especificar en tiempo de diseño. |
Mientras que es aceptable y, a menudo, necesario tener una propiedad de solo lectura, las instrucciones de diseño prohíben utilizar propiedades de solo escritura porque permiten al usuario establecer un valor, y evitar que el usuario vea ese valor no proporciona ninguna seguridad. Además, sin acceso de lectura, no se puede ver el estado de los objetos compartidos, lo que limita su utilidad. |
|
CA1046: No sobrecargar el operador de igualdad en los tipos de referencia |
Para los tipos de referencia, la implementación predeterminada del operador de igualdad casi siempre es correcta. De manera predeterminada, dos referencias son iguales sólo si señalan al mismo objeto. |
Los tipos declaran miembros protegidos para que los tipos heredados puedan obtener acceso o reemplazar el miembro. Por definición, no se puede heredar de tipos sealed, lo que significa que no se puede llamar a los métodos protegidos en tipos sealed. |
|
Los tipos declaran los métodos como virtuales para que los tipos heredados puedan reemplazar la implementación del método virtual. Por definición, no se puede heredar de un tipo sealed. Esto hace que un método virtual en un tipo sealed no tenga sentido. |
|
Los tipos se declaran dentro de los espacios de nombres para evitar conflictos de nombre y como una forma de organizar los tipos relacionados en una jerarquía de objetos. |
|
El uso principal de un campo debe ser como un detalle de implementación. Los campos deben ser privados o internos y deben exponerse utilizando propiedades. |
|
Un tipo público o protegido solamente contiene miembros estáticos y no se declara con el modificador sealed (NotInheritable) (Referencia de C#). Un tipo que no está diseñado para heredarse debería marcarse con el modificador sealed para impedir su uso como tipo base. |
|
CA1053: Los tipos titulares estáticos no deben tener constructores |
Un tipo público o público anidado declara sólo miembros estáticos y tiene un constructor predeterminado público o protegido. El constructor no es necesario puesto que al llamar a los miembros estáticos no se requiere una instancia del tipo. La sobrecarga de la cadena debería llamar a la sobrecarga del identificador URI utilizando el argumento string por motivos de seguridad y protección. |
Si un método toma una representación de cadena de un identificador URI, debe proporcionarse la sobrecarga correspondiente que toma una instancia de la clase URI, que proporciona estos servicios de forma segura. |
|
La regla supone que el método devuelve un identificador uniforme de recursos (URI). Las representaciones de cadena de identificadores URI tienen tendencia a analizar y codificar errores, por lo que pueden crear puntos vulnerables en la seguridad. La clase System.Uri proporciona estos servicios de una manera segura. |
|
La regla supone que la propiedad representa un Identificador uniforme de recursos (URI). Las representaciones de cadena de identificadores URI tienen tendencia a analizar y codificar errores, por lo que pueden crear puntos vulnerables en la seguridad. La clase System.Uri proporciona estos servicios de una manera segura. |
|
CA1057: Las sobrecargas URI de cadena llaman a sobrecargas System.Uri |
Un tipo declara sobrecargas de método que solamente se distinguen por la sustitución de un parámetro de cadena por un parámetro System.Uri. La sobrecarga que toma el parámetro de cadena no llama a la sobrecarga que toma el parámetro URI. |
Un tipo visible externamente extiende algunos tipos base. Utilice una de las alternativas. |
|
CA1059: Los miembros no deben exponer determinados tipos concretos |
Un tipo concreto es un tipo que tiene una implementación completa y, por consiguiente, se pueden crear instancias de él. Para permitir un uso extendido del miembro, reemplace el tipo concreto por la interfaz sugerida. |
Una excepción interna sólo se ve dentro de su propio ámbito interno. Cuando la excepción esté fuera del ámbito interno, sólo se podrá usar la excepción base para detectarla. Si la excepción interna se hereda de T:System.Exception, T:System.SystemException o T:System.ApplicationException, el código externo no tendrá información suficiente para saber qué hacer con la excepción. |
|
CA1500: Los nombres de las variables no deben coincidir con los nombres de los campos |
Un método de instancia declara un parámetro o una variable local cuyo nombre coincide con un campo de instancia del tipo declarativo, lo que da lugar a errores. |
Esta regla mide el número de rutas de acceso independientes de forma lineal a través del método, que es determinado por el número y la complejidad de bifurcaciones condicionales. |
|
Los identificadores de los espacios de nombres, miembros y parámetros no puede distinguirse sólo por mayúsculas o minúsculas porque los lenguajes que tienen como destino el Common Language Runtime no necesitan distinguir entre mayúsculas y minúsculas. |
|
CA1716: Los identificadores no deberían coincidir con palabras clave |
Un nombre de espacio de nombres o un nombre de tipo coinciden con una palabra clave reservada en un lenguaje de programación. Los identificadores para los espacios de nombres y tipos no deberían coincidir con palabras clave definidas por los lenguajes que tienen como destino el Common Language Runtime. |
Una firma de método incluye un parámetro que no se utiliza en el cuerpo del método. |
|
Las variables locales no usadas y las asignaciones innecesarias aumentan el tamaño de un ensamblado y reducen el rendimiento. |
|
Una optimización de rendimiento común consiste en almacenar un valor en un registro del procesador en lugar de en la memoria, lo que se denomina "registrar el valor". Para aumentar la posibilidad de que todas las variables locales se registren, limite el número de variables locales a 64. |
|
CA1810: Inicializar campos estáticos de tipo de referencia insertados |
Cuando un tipo declara un constructor estático explícito, el compilador Just-In-Time (JIT) agrega una comprobación a cada constructor de instancia y a cada método estático del tipo para asegurarse de que se ha llamado anteriormente al constructor estático. Las comprobaciones del constructor estático pueden reducir el rendimiento. |
Un miembro interno o privado (nivel de ensamblado) no tiene llamadores en el ensamblado, no es invocado por Common Language Runtime ni tampoco por un delegado. |
|
El código del ensamblado no crea una instancia del tipo del nivel de ensamblado. |
|
La biblioteca de clases de .NET Framework proporciona métodos para recuperar atributos personalizados. De forma predeterminada, estos métodos buscan la jerarquía de herencia de atributo. La acción de sellar el atributo elimina la búsqueda en la jerarquía de herencia y puede mejorarse el rendimiento. |
|
CA1814: Preferir las matrices escalonadas antes que multidimensionales |
Una matriz escalonada es una matriz cuyos elementos son matrices. Las matrices que constituyen los elementos pueden ser de tamaños diferentes, reduciendo el espacio desaprovechado para algunos conjuntos de datos. |
CA1815: Reemplazar Equals y el operador Equals en los tipos de valor |
Para los tipos de valor, la implementación heredada de Equals utiliza la biblioteca de reflexión y compara el contenido de todos los campos. Mediante el cálculo, la reflexión es cara y no es necesario comparar cada campo para comprobar si hay igualdad. Si espera que los usuarios comparen u ordenen instancias, o utilicen instancias como claves de tabla hash, el tipo de valor debe implementar Equals. |
Las matrices devueltas por las propiedades no están protegidas contra escritura, aun cuando la propiedad es de sólo lectura. Para mantener la matriz inviolable, la propiedad debe devolver una copia de la matriz. Por lo general, los usuarios no entienden las implicaciones de rendimiento adversas que se originan al llamar a este tipo de propiedad. |
|
CA1820: Comprobar si las cadenas están vacías mediante la longitud de cadena |
El uso de la propiedad String.Length o del método String.IsNullOrEmpty para comparar cadenas es mucho más rápido que el uso de Equals. |
Siempre que pueda, evite los finalizadores debido a la sobrecarga de rendimiento adicional necesaria para el seguimiento de la duración del objeto. Un finalizador vacío produce una sobrecarga adicional sin ningún beneficio. |
|
Los miembros que no tienen acceso a datos de instancia o que llaman a métodos de instancia se pueden marcar como static (Shared en Visual Basic). Después de marcar los métodos como static, el compilador emite los sitios de llamada no virtuales para estos miembros. Esto puede proporcionar una mejora apreciable del rendimiento del código en el que el rendimiento es fundamental. |
|
Se detectaron campos privados a los que no parece que se tenga acceso en el ensamblado. |
|
Esto hace que el error original sea difícil de detectar y depurar. |
|
Se define un método de invocación de plataforma y hay un método con la funcionalidad equivalente en la biblioteca de clases de .NET Framework. |
|
CA2208: Crear instancias de las excepciones del argumento correctamente |
Se realiza una llamada al constructor predeterminado (sin parámetros) de un tipo de excepción que es o deriva de ArgumentException, o se pasa un argumento de cadena incorrecto a un constructor con parámetros de un tipo de excepción que es o deriva de ArgumentException. |
Los campos estáticos que no son constantes ni de sólo lectura no son seguros para subprocesos. Obtener acceso a este tipo de campo se debe controlar cuidadosamente y requiere técnicas de programación avanzadas para sincronizar el acceso al objeto de clase. |
|
Una enumeración visible externamente está marcada con FlagsAttribute y tiene uno o varios valores que no son potencias de dos o una combinación de los otros valores definidos en la enumeración. |
|
Cuando se genera una excepción en una cláusula finally o fault, la nueva excepción oculta la excepción activa. Cuando se genera una excepción en una cláusula filter, el runtime la detecta automáticamente. Esto hace que el error original sea difícil de detectar y depurar. |
|
Los finalizadores deben utilizar el modificador de acceso de familia. |
|
No debería cambiar el modificador de acceso para los miembros heredados. Cambiando un miembro heredado a privado no evita que los llamadores tengan acceso a la implementación de la clase base del método. |
|
CA2223: Los miembros deben diferenciarse por algo más que por un tipo de valor devuelto |
Aunque Common Language Runtime permite utilizar tipos de valor devuelto para diferenciar miembros idénticos, esta característica no se encuentra en Common Language Specification ni es una característica común de los lenguajes de programación de .NET. |
CA2224: Reemplazar Equals al sobrecargar operadores de igualdad |
Un tipo público implementa el operador de igualdad, pero no reemplaza Object.Equals. |
CA2225: Las sobrecargas del operador tienen alternativas con nombre |
Se detectó una sobrecarga del operador y no se encontró el método alternativo con el nombre esperado. El miembro alternativo con nombre proporciona acceso a la misma funcionalidad que el operador; esto se hace para los desarrolladores que programan en lenguajes que no admiten operadores sobrecargados. |
Un tipo implementa el operador de igualdad o de desigualdad y no implementa el operador opuesto. |
|
CA2227: Las propiedades de la colección deben ser de solo lectura |
Una propiedad de colección grabable permite al usuario reemplazar la colección por otra diferente. Una propiedad de sólo lectura impide que la colección se reemplace, pero sí permite establecer miembros individuales. |
Un tipo público o protegido contiene un método público o protegido que utiliza la convención de llamada VarArgs en lugar de la palabra clave params. |
|
CA2231: Sobrecargar el operador de igualdad al reemplazar el tipo de valor de igualdad |
Un tipo de valor invalida Object.Equals pero no implementa el operador de igualdad. |
Se realiza una llamada a un método que tiene un parámetro de cadena cuyo nombre contiene "uri", "URI", "urn", "URN", "url" o "URL". El tipo declarativo del método contiene una sobrecarga de método correspondiente que tiene un parámetro System.Uri. |
|
CA2239: Proporcionar métodos de deserialización para campos opcionales |
Un tipo tiene un campo que está marcado con el atributo System.Runtime.Serialization.OptionalFieldAttribute y el tipo no proporciona métodos de control de eventos de deserialización. |