.NET Framework
Tipos personalizados
Buscar..
Observaciones
Normalmente, una struct
se usa solo cuando el rendimiento es muy importante. Dado que los tipos de valor viven en la pila, se puede acceder a ellos mucho más rápido que las clases. Sin embargo, la pila tiene mucho menos espacio que el montón, por lo que las estructuras deben mantenerse pequeñas (Microsoft recomienda que las struct
ocupen más de 16 bytes).
Una class
es el tipo más usado (de estos tres) en C #, y generalmente es lo que debe ir primero.
Se utiliza una enum
siempre que pueda tener una lista clara y clara de elementos que solo deben definirse una vez (en tiempo de compilación). Las enumeraciones son útiles para los programadores como una referencia liviana a algún valor: en lugar de definir una lista de variables constant
para comparar, puede usar una enumeración y obtener soporte de Intellisense para asegurarse de que no use accidentalmente un valor incorrecto.
Definición de Struct
Las estructuras heredan de System.ValueType, son tipos de valor y viven en la pila. Cuando los tipos de valor se pasan como un parámetro, se pasan por valor.
Struct MyStruct
{
public int x;
public int y;
}
Pasado por valor significa que el valor del parámetro se copia para el método, y cualquier cambio realizado en el parámetro en el método no se refleja fuera del método. Por ejemplo, considere el siguiente código, que llama a un método llamado AddNumbers
, que pasa las variables a
y b
, que son de tipo int
, que es un tipo de valor.
int a = 5;
int b = 6;
AddNumbers(a,b);
public AddNumbers(int x, int y)
{
int z = x + y; // z becomes 11
x = x + 5; // now we changed x to be 10
z = x + y; // now z becomes 16
}
A pesar de que hemos añadido a 5 x
dentro del método, el valor de a
se mantiene sin cambios, porque es un tipo de valor, y eso significa que x
era una copia de a
'valor de s, pero en realidad no a
.
Recuerde, los tipos de valor viven en la pila y se pasan por valor.
Definición de clase
Las clases heredadas de System.Object, son tipos de referencia y viven en el montón. Cuando los tipos de referencia se pasan como un parámetro, se pasan por referencia.
public Class MyClass
{
public int a;
public int b;
}
Pasado por referencia significa que una referencia al parámetro se pasa al método, y cualquier cambio en el parámetro se reflejará fuera del método cuando regrese, porque la referencia es exactamente el mismo objeto en la memoria . Usemos el mismo ejemplo que antes, pero primero "envolveremos" los int
en una clase.
MyClass instanceOfMyClass = new MyClass();
instanceOfMyClass.a = 5;
instanceOfMyClass.b = 6;
AddNumbers(instanceOfMyClass);
public AddNumbers(MyClass sample)
{
int z = sample.a + sample.b; // z becomes 11
sample.a = sample.a + 5; // now we changed a to be 10
z = sample.a + sample.b; // now z becomes 16
}
Esta vez, cuando cambiamos sample.a
a 10
, el valor de instanceOfMyClass.a
también cambia, porque se pasó por referencia . Pasado por referencia significa que se pasó al método una referencia (también llamada a veces puntero ) al objeto, en lugar de una copia del objeto en sí.
Recuerde, los tipos de referencia viven en el montón y se pasan por referencia.
Definición de enumeración
Un enum es un tipo especial de clase. La palabra clave enum
le dice al compilador que esta clase hereda de la clase abstracta System.Enum. Las enumeraciones se utilizan para distintas listas de elementos.
public enum MyEnum
{
Monday = 1,
Tuesday,
Wednesday,
//...
}
Puede pensar en una enumeración como una forma conveniente de asignar constantes a algún valor subyacente. La enumeración definida anteriormente declara valores para cada día de la semana y comienza con 1
. Tuesday
se asignaría automáticamente a 2
, el Wednesday
a 3
, etc.
Por defecto, las enumeraciones usan int
como el tipo subyacente y comienzan en 0, pero puede usar cualquiera de los siguientes tipos integrales : byte, sbyte, short, ushort, int, uint, long, or ulong
, y puede especificar valores explícitos para cualquier ít. Si algunos elementos se especifican explícitamente, pero otros no, cada elemento después del último definido se incrementará en 1.
Volveremos a utilizar este ejemplo echando algún otro valor a un MyEnum de este modo:
MyEnum instance = (MyEnum)3; // the variable named 'instance' gets a
//value of MyEnum.Wednesday, which maps to 3.
int x = 2;
instance = (MyEnum)x; // now 'instance' has a value of MyEnum.Tuesday
Otro tipo de enumeración útil, aunque más complejo, se llama Flags
. Al decorar una enumeración con el atributo Flags
, puede asignar una variable más de un valor a la vez. Tenga en cuenta que al hacer esto debe definir los valores explícitamente en la representación de base 2.
[Flags]
public enum MyEnum
{
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64
}
Ahora puede comparar más de un valor a la vez, ya sea utilizando comparaciones a nivel de bits o, si está utilizando .NET 4.0 o posterior, el método Enum.HasFlag
.
MyEnum instance = MyEnum.Monday | MyEnum.Thursday; // instance now has a value of
// *both* Monday and Thursday,
// represented by (in binary) 0100.
if (instance.HasFlag(MyEnum.Wednesday))
{
// it doesn't, so this block is skipped
}
else if (instance.HasFlag(MyEnum.Thursday))
{
// it does, so this block is executed
}
Como la clase Enum se subclasifica de System.ValueType
, se trata como un tipo de valor y se pasa por valor, no por referencia. El objeto base se crea en el montón, pero cuando pasa un valor de enumeración a una llamada de función, una copia del valor que usa el tipo de valor subyacente de Enum (generalmente System.Int32) se inserta en la pila. El compilador rastrea la asociación entre este valor y el objeto base que se creó en la pila. Consulte ValueType Class (System) (MSDN) para obtener más información.