В чем разница между структурой и классом в .NET?

.net class struct value-type reference-type

257322 просмотра

18 ответа

В чем разница между структурой и классом в .NET?

Автор: Keith Источник Размещён: 17.05.2019 03:54

Ответы (18)


866 плюса

Решение

В .NET существует две категории типов, ссылочные типы и типы значений .

Структуры - это типы значений, а классы - ссылочные типы .

Общая разница заключается в том, что ссылочный тип живет в куче, а тип значения живет в строке, т. Е. Где бы ни была ваша переменная или поле.

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

Переменная, содержащая ссылочный тип, содержит указатель или ссылку на другое место в памяти, где находится фактическое значение.

Это имеет одно преимущество, для начала:

  • типы значений всегда содержат значение
  • ссылочные типы могут содержать нуль- ссылку, что означает, что они вообще не ссылаются на что-либо

Внутри ссылочный тип s реализуется как указатели, и, зная, что и зная, как работает переменная, существуют другие поведенческие шаблоны:

  • копируя содержимое переменной типа значения в другую переменную, копирует все содержимое в новую переменную, делая два разных. Другими словами, после копирования изменения в один не влияют на другие
  • копируя содержимое переменной ссылочного типа в другую переменную, копирует ссылку, что означает, что теперь у вас есть две ссылки на то же место хранения фактических данных в другом месте . Другими словами, после копирования изменение данных в одной ссылке будет также влиять на другую, но только потому, что вы действительно просто смотрите на те же данные, что и места

Когда вы объявляете переменные или поля, вот как различаются два типа:

  • variable: тип значения живет в стеке, ссылочный тип живет в стеке как указатель на где-то в памяти кучи, где живет реальная память (хотя обратите внимание на статью серии Eric Lipperts: The Stack Is Detail Detail .)
  • class / struct-field: тип значения живет полностью внутри типа, ссылочный тип живет внутри типа в качестве указателя на где-то в памяти кучи, где живет реальная память.
Автор: Lasse Vågsæther Karlsen Размещён: 16.08.2008 06:41

146 плюса

Краткий обзор каждого из них:

Только классы:

  • Может поддерживать наследование
  • Являются ли ссылочные (указательные) типы
  • Ссылка может быть нулевой
  • Накладные расходы памяти на новый экземпляр

Только для структур:

  • Не удается поддерживать наследование
  • Типы значений
  • Передаются по значению (например, целые числа)
  • Не может иметь нулевую ссылку (если не используется Nullable)
  • У вас нет издержек на память для каждого нового экземпляра,

Оба класса и структуры:

  • Являются ли составные типы данных обычно используемыми, чтобы содержать несколько переменных, которые имеют некоторые логические отношения
  • Может содержать методы и события
  • Может поддерживать интерфейсы
Автор: Thomas Bratt Размещён: 04.10.2008 10:07

28 плюса

В .NET описания конструкций и классов различаются между ссылочными типами и типами значений.

Когда вы обходите ссылочный тип, на самом деле хранится только один. Весь код, который обращается к экземпляру, обращается к тому же самому.

Когда вы передаете тип значения, каждый из них является копией. Весь код работает над собственной копией.

Это можно показать на примере:

struct MyStruct 
{
    string MyProperty { get; set; }
}

void ChangeMyStruct(MyStruct input) 
{ 
   input.MyProperty = "new value";
}

...

// Create value type
MyStruct testStruct = new MyStruct { MyProperty = "initial value" }; 

ChangeMyStruct(testStruct);

// Value of testStruct.MyProperty is still "initial value"
// - the method changed a new copy of the structure.

Для класса это было бы иначе

class MyClass 
{
    string MyProperty { get; set; }
}

void ChangeMyClass(MyClass input) 
{ 
   input.MyProperty = "new value";
}

...

// Create reference type
MyClass testClass = new MyClass { MyProperty = "initial value" };

ChangeMyClass(testClass);

// Value of testClass.MyProperty is now "new value" 
// - the method changed the instance passed.

Классы могут быть ничем - ссылка может указывать на нуль.

Структуры - это фактическое значение - они могут быть пустыми, но никогда не равными нулю. По этой причине у структур всегда есть конструктор по умолчанию без параметров - им нужно «начальное значение».

Автор: Keith Размещён: 16.08.2008 08:30

16 плюса

В дополнение ко всем различиям, описанным в других ответах:

  1. Структуры не могут иметь явный конструктор без параметров, тогда как класс может
  2. Структуры не могут иметь деструкторов , тогда как класс может
  3. Структуры не могут наследовать от другой структуры или класса, тогда как класс может наследовать от другого класса. (Обе структуры и классы могут реализовывать из интерфейса.)

Если вы читаете видео, объясняющее все различия, вы можете проверить Part 29 - C # Tutorial - Различие между классами и структурами на C # .

Автор: Venkat Размещён: 14.06.2012 04:57

14 плюса

Экземпляры классов хранятся в управляемой куче. Все переменные, содержащие «экземпляр», являются просто ссылкой на экземпляр в куче. Передача объекта методу приводит к копированию передаваемой ссылки, а не к самому объекту.

Структуры (технически, типы значений) хранятся везде, где они используются, подобно примитивному типу. Содержимое может быть скопировано во время выполнения в любое время и без вызова настраиваемого конструктора-копии. Передача типа значения в метод включает в себя копирование всего значения, опять же без использования какого-либо настраиваемого кода.

Различие улучшается с помощью имен C ++ / CLI: «ref class» - это класс, как описано выше, «класс значений» - это класс, описанный во втором. Ключевые слова «class» и «struct», используемые C #, - это просто то, что нужно изучить.

Автор: Zooba Размещён: 16.08.2008 12:16

11 плюса

От выбора Microsoft от класса и структуры ...

Как правило, большинство типов в структуре должны быть классами. Однако есть некоторые ситуации, в которых характеристики типа значения делают более уместным использование структур.

Сформулируйте структуру вместо класса:

  • Если экземпляры типа являются небольшими и обычно недолговечными или обычно внедряются в другие объекты.

X ИЗБЕГАЙТЕ структуру, если тип имеет все следующие характеристики:

  • Он логически представляет одно значение, подобное примитивным типам (int, double и т. Д.).
  • Он имеет размер экземпляра до 16 байт.
  • Это неизменно. (нельзя изменить)
  • Его не нужно часто вставлять в бокс.
Автор: Sunsetquest Размещён: 14.05.2017 07:58

7 плюса

Разница между Struts и классами -

  • Структуры - это тип значения, тогда как классы - ссылочный тип .
  • Структуры хранятся в стеке, тогда как классы хранятся в куче .
  • Типы значений хранят свое значение в памяти, где они объявлены, но ссылочный тип содержит ссылку на память объекта.
  • Типы значений, уничтоженные сразу же после того, как область потеряна, тогда как ссылочный тип только уничтожает переменную после того, как область потеряна. Объект позже уничтожается сборщиком мусора.
  • Когда вы копируете структуру в другую структуру, новая копия этой структуры создается, модифицированная одной структурой, не влияет на значение другой структуры.
  • Когда вы копируете класс в другой класс, он копирует только ссылочную переменную.
  • И ссылочная переменная указывает на тот же объект в куче. Изменение одной переменной повлияет на другую ссылочную переменную.
  • Структуры не могут иметь деструкторы , но классы могут иметь деструкторы.
  • Структуры не могут иметь явные конструкторы без параметров, тогда как класс может структурировать не наследование, а классы. Оба поддерживают наследование от интерфейса.
  • Структуры герметичны .
Автор: shana Размещён: 05.01.2018 01:58

5 плюса

Структура против класса

Структура - тип значения, поэтому она хранится в стеке, но класс является ссылочным типом и хранится в куче.

Структура не поддерживает наследование и полиморфизм, но класс поддерживает оба.

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

Поскольку структура представляет собой тип значения, мы не можем присваивать null объекту struct, но это не относится к классу.

Автор: Swagatika dhal Размещён: 06.11.2009 08:02

5 плюса

Чтобы сделать его полным, существует другая разница при использовании Equalsметода, который наследуется всеми классами и структурами.

Допустим, у нас есть класс и структура:

class A{
  public int a, b;
}
struct B{
  public int a, b;
}

и в методе Main мы имеем 4 объекта.

static void Main{
  A c1 = new A(), c2 = new A();
  c1.a = c1.b = c2.a = c2.b = 1;
  B s1 = new B(), s2 = new B();
  s1.a = s1.b = s2.a = s2.b = 1;
}

Затем:

s1.Equals(s2) // true
s1.Equals(c1) // false
c1.Equals(c2) // false
c1 == c2 // false

Таким образом , структуры подходят для числовых объектов, например точек (сохраняют координаты x и y). И классы подходят для других. Даже если у 2 человек одинаковое имя, высота, вес ..., они все еще 2 человека.

Автор: Ning Размещён: 02.08.2017 01:34

4 плюса

Ну, для начала, структура передается по значению, а не по ссылке. Структуры хороши для относительно простых структур данных, тогда как классы обладают большей гибкостью с архитектурной точки зрения с помощью полиморфизма и наследования.

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

Автор: Ed S. Размещён: 16.08.2008 08:27

3 плюса

Помимо основного различия спецификатора доступа и нескольких упомянутых выше я хотел бы добавить некоторые из основных различий, в том числе немногие из упомянутых выше, с образцом кода с выходом, который даст более четкое представление о ссылке и значении

Структуры:

  • Типы значений и не требуют распределения кучи.
  • Распределение памяти различно и хранится в стеке
  • Полезно для небольших структур данных
  • Влияем на производительность, когда мы передаем значение методу, мы передаем всю структуру данных, и все передается в стек.
  • Конструктор просто возвращает значение самой структуры (обычно во временном месте в стеке), и это значение затем копируется по мере необходимости
  • Каждый из переменных имеет свою собственную копию данных, и невозможно, чтобы операции над ними влияли на другую.
  • Не поддерживайте заданное пользователем наследование, и они неявно наследуют от объекта типа

Учебный класс:

  • Значение ссылочного типа
  • Хранится в куче
  • Хранить ссылку на динамически выделенный объект
  • Конструкторы вызываются с новым оператором, но это не выделяет память на кучу
  • Несколько переменных могут иметь ссылку на один и тот же объект
  • Операции с одной переменной могут влиять на объект, на который ссылается другая переменная

Образец кода

    static void Main(string[] args)
    {
        //Struct
        myStruct objStruct = new myStruct();
        objStruct.x = 10;
        Console.WriteLine("Initial value of Struct Object is: " + objStruct.x);
        Console.WriteLine();
        methodStruct(objStruct);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Struct Object is: " + objStruct.x);
        Console.WriteLine();

        //Class
        myClass objClass = new myClass(10);
        Console.WriteLine("Initial value of Class Object is: " + objClass.x);
        Console.WriteLine();
        methodClass(objClass);
        Console.WriteLine();
        Console.WriteLine("After Method call value of Class Object is: " + objClass.x);
        Console.Read();
    }
    static void methodStruct(myStruct newStruct)
    {
        newStruct.x = 20;
        Console.WriteLine("Inside Struct Method");
        Console.WriteLine("Inside Method value of Struct Object is: " + newStruct.x);
    }
    static void methodClass(myClass newClass)
    {
        newClass.x = 20;
        Console.WriteLine("Inside Class Method");
        Console.WriteLine("Inside Method value of Class Object is: " + newClass.x);
    }
    public struct myStruct
    {
        public int x;
        public myStruct(int xCons)
        {
            this.x = xCons;
        }
    }
    public class myClass
    {
        public int x;
        public myClass(int xCons)
        {
            this.x = xCons;
        }
    }

Выход

Начальное значение объекта Struct: 10

Внутренний метод Struct Внутри значения метода объекта Struct: 20

После значения вызова метода объекта Struct: 10

Начальное значение объекта класса: 10

Метод внутри класса Внутри Значение метода объекта класса: 20

После значения вызова метода объекта класса: 20

Здесь вы можете четко видеть разницу между вызовом по значению и вызовом по ссылке.

Автор: Arijit Mukherjee Размещён: 29.05.2014 09:45

3 плюса

  1. События, объявленные в классе, имеют свой + = и - = доступ, автоматически заблокированный с помощью блокировки (это), чтобы сделать их потокобезопасными (статические события заблокированы для типа класса). События, объявленные в структуре, не имеют автоматического блокирования доступа + = и - =. Блокировка (это) для структуры не будет работать, поскольку вы можете заблокировать только выражение ссылочного типа.

  2. Создание экземпляра структуры не может вызвать сбор мусора (если конструктор прямо или косвенно не создает экземпляр ссылочного типа), тогда как создание экземпляра ссылочного типа может вызвать сбор мусора.

  3. Структура всегда имеет встроенный публичный конструктор по умолчанию.

    class DefaultConstructor
    {
        static void Eg()
        {
            Direct     yes = new   Direct(); // Always compiles OK
            InDirect maybe = new InDirect(); // Compiles if constructor exists and is accessible
            //...
        }
    }
    

    Это означает, что структура всегда актуальна, тогда как класс может не быть, поскольку все его конструкторы могут быть частными.

    class NonInstantiable
    {
        private NonInstantiable() // OK
        {
        }
    }
    
    struct Direct
    {
        private Direct() // Compile-time error
        {
        }
    }
    
  4. У структуры не может быть деструктора. Деструктор - это просто переопределение объекта. Финализация в маскировке, а структуры, являющиеся типами значений, не подлежат сборке мусора.

    struct Direct
    {
        ~Direct() {} // Compile-time error
    }
    class InDirect
    {
        ~InDirect() {} // Compiles OK
    }
    
    And the CIL for ~Indirect() looks like this:
    
    .method family hidebysig virtual instance void
            Finalize() cil managed
    {
      // ...
    } // end of method Indirect::Finalize
    
  5. Структура неявно запечатана, класс - нет.
    Структура не может быть абстрактной, класс может.
    Структуру нельзя вызвать: base () в своем конструкторе, тогда как класс без явного базового класса может.
    Строка не может расширять другой класс, класс может.
    Структура не может объявлять защищенные члены (например, поля, вложенные типы), которые могут иметь классы.
    Структура не может объявлять элементы абстрактной функции, может быть абстрактный класс.
    Структура не может объявлять члены виртуальной функции, класс может.
    Структура не может объявлять закрытые члены функции, класс может.
    Строка не может объявлять элементы функции переопределения, класс может.
    Единственным исключением из этого правила является то, что структура может переопределять виртуальные методы System.Object, а именно: Equals () и GetHashCode () и ToString ().

Автор: Humble Coder Размещён: 25.07.2011 05:24

3 плюса

Как уже упоминалось ранее: Классы являются ссылочным типом, в то время как Structs являются типами значений со всеми последствиями.

Как правило, правило Framework Design Guidelines рекомендует использовать Struct вместо классов, если:

  • Он имеет размер экземпляра под 16 байтами
  • Он логически представляет одно значение, подобное примитивным типам (int, double и т. Д.),
  • Он неизменен
  • Он не обязательно должен быть в коробке часто
Автор: kb9 Размещён: 23.09.2015 11:32

3 плюса

Чтобы добавить к другим ответам, есть одно фундаментальное отличие, которое стоит отметить, и именно так оно хранится в памяти. Это может существенно повлиять на производительность массивов. Структуры - это типы значений, поэтому они сохраняют значение в области памяти, на которую они указывают, классы являются ссылочными типами, поэтому они ссылаются на класс в области памяти, на которую они указывают, фактическое значение хранится в другом месте.

  • С помощью структуры память выделяется внутри содержащего класса для хранения данных.
  • С классом содержащий класс будет содержать указатель на новый класс в другой области памяти.

Это также относится к массивам, поэтому массив структур выглядит так в памяти

[struct][struct][struct][struct][struct][struct][struct][struct]

Где в виде массива классов выглядит так

[pointer][pointer][pointer][pointer][pointer][pointer][pointer][pointer]

Фактические значения, которые вас интересуют, фактически не хранятся в массиве, а в других местах памяти.

Однако для подавляющего большинства приложений это различие не имеет особого значения, но в высокопроизводительном коде это будет определять локальность данных в памяти и существенно повлиять на производительность кэша CPU. Использование классов, когда вы могли / должны были использовать структуры, будет значительно увеличивать количество промахов в кэше CPU.

Самая медленная вещь, которую делает современный процессор, - это не количество хруста, она извлекает данные из памяти, а кэш-память L1 во много раз быстрее, чем чтение данных из ОЗУ.

Автор: Will Calderwood Размещён: 25.08.2015 01:00

1 плюс

Структуры - это фактическое значение - они могут быть пустыми, но не равными нулю

Это правда, однако также обратите внимание, что с .NET 2 structs поддерживает версию Nullable, а C # предоставляет некоторый синтаксический сахар, чтобы упростить его использование.

int? value = null;
value  = 1;
Автор: denis phillips Размещён: 16.08.2008 02:03

1 плюс

There is one interesting case of "class vs struct" puzzle - situation when you need to return several results from the method: choose which to use. If you know the ValueTuple story - you know that ValueTuple (struct) was added because it should be more effective then Tuple (class). But what does it mean in numbers? Two tests: one is struct/class that have 2 fields, other with struct/class that have 8 fields (with dimension more then 4 - class should become more effective then struct in terms processor ticks, but of course GC load also should be considered).

P.S. Another benchmark for specific case 'sturct or class with collections' is there: https://stackoverflow.com/a/45276657/506147

BenchmarkDotNet=v0.10.10, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233540 Hz, Resolution=309.2586 ns, Timer=TSC
.NET Core SDK=2.0.3
  [Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
  Clr    : .NET Framework 4.7 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.2115.0
  Core   : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT


            Method |  Job | Runtime |     Mean |     Error |    StdDev |      Min |      Max |   Median | Rank |  Gen 0 | Allocated |
------------------ |----- |-------- |---------:|----------:|----------:|---------:|---------:|---------:|-----:|-------:|----------:|
  TestStructReturn |  Clr |     Clr | 17.57 ns | 0.1960 ns | 0.1834 ns | 17.25 ns | 17.89 ns | 17.55 ns |    4 | 0.0127 |      40 B |
   TestClassReturn |  Clr |     Clr | 21.93 ns | 0.4554 ns | 0.5244 ns | 21.17 ns | 23.26 ns | 21.86 ns |    5 | 0.0229 |      72 B |
 TestStructReturn8 |  Clr |     Clr | 38.99 ns | 0.8302 ns | 1.4097 ns | 37.36 ns | 42.35 ns | 38.50 ns |    8 | 0.0127 |      40 B |
  TestClassReturn8 |  Clr |     Clr | 23.69 ns | 0.5373 ns | 0.6987 ns | 22.70 ns | 25.24 ns | 23.37 ns |    6 | 0.0305 |      96 B |
  TestStructReturn | Core |    Core | 12.28 ns | 0.1882 ns | 0.1760 ns | 11.92 ns | 12.57 ns | 12.30 ns |    1 | 0.0127 |      40 B |
   TestClassReturn | Core |    Core | 15.33 ns | 0.4343 ns | 0.4063 ns | 14.83 ns | 16.44 ns | 15.31 ns |    2 | 0.0229 |      72 B |
 TestStructReturn8 | Core |    Core | 34.11 ns | 0.7089 ns | 1.4954 ns | 31.52 ns | 36.81 ns | 34.03 ns |    7 | 0.0127 |      40 B |
  TestClassReturn8 | Core |    Core | 17.04 ns | 0.2299 ns | 0.2150 ns | 16.68 ns | 17.41 ns | 16.98 ns |    3 | 0.0305 |      96 B |

Code test:

using System;
using System.Text;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Columns;
using BenchmarkDotNet.Attributes.Exporters;
using BenchmarkDotNet.Attributes.Jobs;
using DashboardCode.Routines.Json;

namespace Benchmark
{
    //[Config(typeof(MyManualConfig))]
    [RankColumn, MinColumn, MaxColumn, StdDevColumn, MedianColumn]
    [ClrJob, CoreJob]
    [HtmlExporter, MarkdownExporter]
    [MemoryDiagnoser]
    public class BenchmarkStructOrClass
    {
        static TestStruct testStruct = new TestStruct();
        static TestClass testClass = new TestClass();
        static TestStruct8 testStruct8 = new TestStruct8();
        static TestClass8 testClass8 = new TestClass8();
        [Benchmark]
        public void TestStructReturn()
        {
            testStruct.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn()
        {
            testClass.TestMethod();
        }


        [Benchmark]
        public void TestStructReturn8()
        {
            testStruct8.TestMethod();
        }

        [Benchmark]
        public void TestClassReturn8()
        {
            testClass8.TestMethod();
        }

        public class TestStruct
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestClass
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance = ++i;
                return x;
            }
        }

        public class TestStruct8
        {
            public int Number = 5;
            public struct StructType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private StructType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private StructType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private StructType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private StructType<int> Method4(int i)
            {
                var x = new StructType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }

        public class TestClass8
        {
            public int Number = 5;
            public class ClassType<T>
            {
                public T Instance1;
                public T Instance2;
                public T Instance3;
                public T Instance4;
                public T Instance5;
                public T Instance6;
                public T Instance7;
                public List<string> List;
            }

            public int TestMethod()
            {
                var s = Method1(1);
                return s.Instance1;
            }

            private ClassType<int> Method1(int i)
            {
                return Method2(++i);
            }

            private ClassType<int> Method2(int i)
            {
                return Method3(++i);
            }

            private ClassType<int> Method3(int i)
            {
                return Method4(++i);
            }

            private ClassType<int> Method4(int i)
            {
                var x = new ClassType<int>();
                x.List = new List<string>();
                x.Instance1 = ++i;
                return x;
            }
        }
    }
}
Автор: Roman Pokrovskij Размещён: 18.12.2017 08:21

1 плюс

+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
|                       |                                                Struct                                                |                                               Class                                               |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
| Type                  | Value-type                                                                                           | Reference-type                                                                                    |
| Where                 | On stack / Inline in containing type                                                                 | On Heap                                                                                           |
| Deallocation          | Stack unwinds / containing type gets deallocated                                                     | Garbage Collected                                                                                 |
| Arrays                | Inline, elements are the actual instances of the value type                                          | Out of line, elements are just references to instances of the reference type residing on the heap |
| Aldel Cost            | Cheap allocation-deallocation                                                                        | Expensive allocation-deallocation                                                                 |
| Memory usage          | Boxed when cast to a reference type or one of the interfaces they implement,                         | No boxing-unboxing                                                                                |
|                       | Unboxed when cast back to value type                                                                 |                                                                                                   |
|                       | (Negative impact because boxes are objects that are allocated on the heap and are garbage-collected) |                                                                                                   |
| Assignments           | Copy entire data                                                                                     | Copy the reference                                                                                |
| Change to an instance | Does not affect any of its copies                                                                    | Affect all references pointing to the instance                                                    |
| Mutability            | Should be immutable                                                                                  | Mutable                                                                                           |
| Population            | In some situations                                                                                   | Majority of types in a framework should be classes                                                |
| Lifetime              | Short-lived                                                                                          | Long-lived                                                                                        |
| Destructor            | Cannot have                                                                                          | Can have                                                                                          |
| Inheritance           | Only from an interface                                                                               | Full support                                                                                      |
| Polymorphism          | No                                                                                                   | Yes                                                                                               |
| Sealed                | Yes                                                                                                  | When have sealed keyword                                                                          |
| Constructor           | Can not have explicit parameterless constructors                                                     | Any constructor                                                                                   |
| Null-assignments      | When marked with nullable question mark                                                              | Yes                                                                                               |
| Abstract              | No                                                                                                   | When have abstract keyword                                                                        |
| Access Modifiers      | public, private, internal                                                                            | public, protected, internal, protected internal, private protected                                |
+-----------------------+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------+
Автор: 0xaryan Размещён: 26.07.2018 10:43

0 плюса

Каждая переменная или поле типа примитивного типа или типа структуры содержит уникальный экземпляр этого типа, включая все его поля (общедоступные и частные). Напротив, переменные или поля ссылочных типов могут иметь значение NULL или ссылаться на объект, хранящийся в другом месте, к которому может также иметься любое количество других ссылок. Поля структуры будут храниться в том же месте, что и переменная или поле этого типа структуры, которое может быть либо в стеке, либо может быть частью другого объекта кучи.

Создание переменной или поля типа примитивного значения создаст его со значением по умолчанию; создание переменной или поля типа структуры создаст новый экземпляр, создав все поля в нем по умолчанию. Создание нового экземпляра ссылочного типа начинается с создания всех полей в нем по умолчанию, а затем запускается дополнительный дополнительный код в зависимости от типа.

Копирование одной переменной или поля примитивного типа в другое будет скопировать значение. Копирование одной переменной или поля типа структуры в другую будет скопировать все поля (публичные и частные) прежнего экземпляра в последний экземпляр. Копирование одной переменной или поля ссылочного типа в другой приведет к тому, что последний ссылается на тот же экземпляр, что и первый (если есть).

Важно отметить, что на некоторых языках, таких как C ++, семантическое поведение типа не зависит от того, как оно хранится, но это не относится к .NET. Если тип реализует изменчивую семантику значений, копирование одной переменной этого типа в другую копирует свойства первого в другой экземпляр, на который ссылается второй, и использование члена второго для его мутации приведет к изменению второго экземпляра , но не первый. Если тип реализует изменчивую ссылочную семантику, копирование одной переменной в другую и использование члена второго для мутирования объекта повлияет на объект, на который ссылается первая переменная; типы с неизменяемой семантикой не допускают мутации, поэтому семантически не имеет значения, копирует ли новый экземпляр или создает другую ссылку на первую.

В .NET можно использовать типы значений для реализации любой из вышеприведенных семантик, при условии, что все их поля могут действовать аналогичным образом. Однако ссылочный тип может реализовывать только изменяемую ссылочную семантику или неизменяемую семантику; типы значений с полями изменяемых ссылочных типов ограничены либо реализацией изменчивой ссылочной семантики, либо странной гибридной семантикой.

Автор: supercat Размещён: 02.12.2011 12:10
32x32