objetos - sintaxis c#
C#Clase estática vs struct para cadenas predefinidas (13)
Un compañero de trabajo acaba de crear la siguiente construcción en C # (el código de ejemplo está simplificado). Su objetivo era acortar la notación para todas las cadenas predefinidas en el resto del código.
public struct PredefinedStrings
{
public const string VeryLongName = "Very Long Name";
public const string AnotherVeryLongName = "Another Very Long Name";
public const string TheLastVeryLongName = "The Last Very Long Name";
}
public static void MethodThatUsesTheNames()
{
Console.WriteLine(PredefinedStrings.VeryLongName);
Console.WriteLine(PredefinedStrings.AnotherVeryLongName);
Console.WriteLine(PredefinedStrings.TheLastVeryLongName);
}
Aunque parece funcionar bien para él, no puedo dejar de preguntarme si debería haber usado una clase estática en lugar de una estructura o si hay una manera más elegante de lograr esto.
¿Cuál sería la forma preferida de hacer esto? Por favor, también explica por qué.
Además de una static class
y una struct
static class
, ¿por qué no considerar el uso de archivos de resource
para cadenas constantes? Se puede acceder fácilmente a estos SomeNamespace.ResourceName.KeyName
como SomeNamespace.ResourceName.KeyName
, y dependiendo de dónde se encuentren en su proyecto se pueden administrar externamente sin volver a compilar si es necesario ...
Con la solución struct
, no hay nada que impida que otro código haga new PredefinedStrings()
, lo que no hará nada malo , pero es algo que es semánticamente confuso de permitir. Con una clase estática, el compilador prohibirá la creación para usted. Y es evidente que la clase estática es la forma preferida de proporcionar constantes en el Framework.
editar para agregar, dije esa segunda parte sin pruebas: desde entonces busqué y encontré razonablemente rápidamente System.Net.Mime.DispositionTypeNames
y System.Net.WebRequestMethods.Http
.
Creo que la estática es mejor y este es mi razonamiento. Si este código vive en alguna biblioteca, y otra parte del código consume esta biblioteca, si el valor de los campos constantes cambia, entonces no solo será necesario volver a compilar esta biblioteca (duh), sino que deberá recompilar el código que consume este código. biblioteca también. La razón para esto es que la compilación inserta los valores constantes donde quiera que los referencia. Sin embargo, si usa static, no tendrá este problema, ya que está haciendo referencia al campo, no al valor .
El simple hecho de que se le permite crear un objeto nuevo que pretende ser una constante es una clara evidencia de mala práctica (generalmente). Digo "habitualmente" porque .NET utiliza el concepto ocasionalmente, aunque no está claro por qué.
Por supuesto, siempre puedes hacer cosas como esta:
public class Foo
{
public struct Bar
{
public static double A = 100;
public Bar(double a)
{
A = a;
}
}
}
Que justifica técnicamente la creación de Bar
; sin embargo, no hay garantía de que la Bar
constante sea siempre la misma (incluso en un entorno de subproceso único) y, en última instancia, es de poca utilidad.
En mi práctica para este propósito usamos Dictionary<enumNameType, string>
. Donde enumNameType es el tipo diferente de nombres que puede tener (en su caso) ... Este diccionario está envuelto en una clase estática y se almacena en caché; lo creamos justo la primera vez que lo usamos y luego devolvemos el mismo objeto ...
¡Espero que esto te sea útil también!
Las estructuras normalmente se evitan a menos que cumplan con ciertos criterios como se detalla en esta respuesta .
Como su compañero de trabajo no lo está usando para almacenar un valor, debería usar una clase, no una estructura.
No hay nada funcionalmente incorrecto con este código. Pero estilísticamente estoy de acuerdo en que una clase estática es mejor. Una clase estática declara que la intención del tipo es solo contener datos estáticos / constantes.
No olvide la recomendación de que un tamaño de estructura debe ser de aproximadamente 16 bytes. Dado un sistema de 32 bits, eso es 4 referencias de System.String allí mismo. Diría que estás mejor con una clase estática si aumenta el número de cadenas.
Parece que estás buscando un archivo de recursos (.resx). Es un lugar decente para almacenar tales cadenas, y abstraer sus cadenas en .resx facilitará la localización de su aplicación en el futuro. La página de MSDN en http://msdn.microsoft.com/en-us/library/1ztca10y.aspx es un comienzo decente para obtener más información.
Preferiría que las cadenas estuvieran en un archivo de recursos y no estén incluidas en el código, principalmente por razones de internacionalización. A continuación, se puede acceder a través de una clase estática con los valores como miembros de la propiedad.
Regla simple: nunca use estructuras hasta que no tenga otra opción.
Las constantes tienen un par de inconvenientes:
- solo se pueden usar tipos simples (cadenas, numéricos, etc.)
- las constantes se inyectan en conjuntos de referencia. Si vuelve a compilar el ensamblado con constantes y no vuelve a compilar el ensamblaje que usa constantes, se meterá en problemas
Escribiría su código de esta manera (aviso cambiar el nombre de la refactorización también):
public static class KnownNames
{
public static readonly string VeryLong = "Very Long Name";
public static readonly string AnotherVeryLong = "Another Very Long Name";
public static readonly string TheLastVeryLong = "The Last Very Long Name";
}
También uso structs para constantes, pero solo para uso interno, no para API públicas. Se siente natural ya que las enumeraciones también se convierten en estructuras.
la clase estática parece ser la mejor opción porque es la más estándar y esperada. Pensé que las versiones de struct / const podrían ser más rápidas, pero después de algunas pruebas no lo fueron.
Aquí están los resultados de mi prueba rápida que incluyó longitud, comparación, concat, copy, indexOf y Substring. Se ejecutó bajo .Net 4.0 en la versión sin un depurador adjunto.
.Net 3.0 .Net 4.0
static class with static read-only string: 0.217 0.364 seconds
static class with const string: 0.211 0.361 seconds
struct with static read-only string: 0.211 0.372 seconds
struct with const string: 0.214 0.371 seconds
Properties.Resources string: 1.173 1.268 seconds
Todos tenían el mismo rendimiento, excepto cuando usaban un archivo de recursos, que es más lento. Si bien Properties.Resources es más lento, no se almacena en el ejecutable, por lo que puede ser más apropiado en algunos casos. Así que use "clase estática" o propiedades. Recursos almacenando cadenas en mi opinión.