Поиск…


замечания

Обычно struct используется только тогда, когда производительность очень важна. Поскольку типы значений живут в стеке, их можно получить гораздо быстрее, чем классы. Однако в стеке гораздо меньше места, чем куча, поэтому структуры должны быть небольшими (Microsoft рекомендует, чтобы struct s занимала не более 16 байт).

class является наиболее часто используемым типом (из этих трех) в C #, и, как правило, вы должны идти первым.

enum используется всякий раз, когда вы можете иметь четко определенный, отличный список элементов, которые нужно определить только один раз (во время компиляции). Перечисления полезны для программистов как облегченная ссылка на какое-то значение: вместо определения списка constant переменных для сравнения вы можете использовать перечисление и получать поддержку Intellisense, чтобы убедиться, что вы случайно не используете неправильное значение.

Определение структуры

Структуры, наследуемые от System.ValueType, являются типами значений и живут в стеке. Когда типы значений передаются как параметр, они передаются по значению.

Struct MyStruct
{
    public int x;
    public int y;
}

Передано по значению означает, что значение параметра копируется для метода, и любые изменения, внесенные в параметр в методе, не отражаются вне метода. Например, рассмотрим следующий код, который вызывает метод с именем AddNumbers , передающий переменные a и b , которые имеют тип int , который является типом Value.

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
} 

Даже если мы добавили 5 к x внутри метода, значение остается неизменным, потому что это тип значения, и это означает , что a x была копия a «значение с, но на самом деле не . a

Помните, что типы значений живут в стеке и передаются по значению.

Определение класса

Классы, наследуемые от System.Object, являются ссылочными типами и живут в куче. Когда ссылочные типы передаются в качестве параметра, они передаются по ссылке.

public Class MyClass
{
    public int a;
    public int b;
}

Передано по ссылке означает, что ссылка на параметр передается методу, и любые изменения параметра будут отражаться вне метода, когда он вернется, потому что ссылка относится к одному и тому же объекту в памяти . Давайте используем тот же пример, что и раньше, но сначала будем «обертывать» int s в классе.

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
} 

На этот раз, когда мы изменили sample.a на 10 , значение instanceOfMyClass.a также изменяется, потому что оно было передано по ссылке . Передано ссылкой означает, что ссылка (также иногда называемая указателем ) на объект передавалась в метод вместо копии самого объекта.

Помните, что типы ссылок живут в куче и передаются по ссылке.

Определение Enum

Перечисление - это особый тип класса. Ключевое слово enum сообщает компилятору, что этот класс наследуется от абстрактного класса System.Enum. Перечисления используются для отдельных списков элементов.

public enum MyEnum
{
    Monday = 1,
    Tuesday,
    Wednesday,
    //...
}

Вы можете представить себе перечисление как удобный способ сопоставления констант с некоторым базовым значением. Перечисленное выше, объявляет значения для каждого дня недели и начинается с 1 . Tuesday автоматически будет отображаться на 2 , в Wednesday до 3 и т. Д.

По умолчанию перечисления используют int как базовый тип и начинаются с 0, но вы можете использовать любой из следующих интегральных типов : byte, sbyte, short, ushort, int, uint, long, or ulong и можете указывать явные значения для любого вещь. Если некоторые элементы явно указаны, но некоторые из них не указаны, каждый элемент после последнего определенного будет увеличен на 1.

Мы хотели бы использовать этот пример литья другого значения для MyEnum как так:

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

Другой полезный, хотя и более сложный тип перечисления называется Flags . При украшении перечисления с на Flags атрибутов, вы можете присвоить переменное более одного значения в то время. Обратите внимание: при этом вы должны явно определять значения в представлении базы 2.

[Flags]
public enum MyEnum
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32, 
    Sunday = 64
}

Теперь вы можете сравнивать более одного значения за раз, используя побитовое сравнение или, если вы используете .NET 4.0 или новее, встроенный метод 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
}

Поскольку класс Enum подклассифицирован из System.ValueType , он рассматривается как тип значения и передается по значению, а не по ссылке. Базовый объект создается в куче, но когда вы передаете значение перечисления в вызов функции, копия значения, использующего базовый тип значения Enum (обычно System.Int32), помещается в стек. Компилятор отслеживает связь между этим значением и базовым объектом, который был создан в стеке. Дополнительную информацию см. В разделе ValueType Class (System) (MSDN) .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow