В .NET и C # все является объектом
Проще говоря.
Даже тип значения, struct, интерфейс и перечисление.
Нельзя утверждать, но дело в том, что все является объектами, кроме указателей / ссылок и литералов из двоичных файлов, даже оптимизированных для ЦП примитивных типов, поскольку это теория ООП, а также. NET и, следовательно, факты.
Из dotnet / csharplang / Type:
Типы значений отличаются от ссылочных типов тем, что переменные типов значений непосредственно содержат свои данные, тогда как переменные ссылочных типов хранят ссылки на свои данные, последние известны как объекты. С ссылочными типами две переменные могут ссылаться на один и тот же объект, и, следовательно, операции с одной переменной могут влиять на объект, на который ссылается другая переменная. В типах значений каждая переменная имеет свою собственную копию данных, и операции с одной из них не могут повлиять на другую.
Система типов C # унифицирована, так что значение любого типа можно рассматривать как объект. Каждый тип в C # прямо или косвенно является производным от типа класса объекта, а объект является окончательным базовым классом всех типов. Значения ссылочных типов обрабатываются как объекты, просто просматривая значения как объект типа. Значения типов значений обрабатываются как объекты путем выполнения операций упаковки и распаковки (упаковки и распаковки).
Тем не менее, фактически, типы значений являются объектами, даже если в IL они управляются ссылками, что называется унифицированной системой типов. При этом все является объектом, но некоторые из них используются через ссылки на значения, а другие через значения. Таким образом, C # - это True OOP, но не Pure, в основном для целей оптимизации.
В IL все является класс. Все. За исключением базовых указателей и, следовательно, регистров ЦП и литералов, ранее связанных с объектом.
Мы можем проверить, является ли какая-либо переменная типом объекта, и все всегда верно (Fiddle)
Все строки, числа, перечисления, структуры, классы и интерфейсы для объектов являются объектами, являющимися типом объекта. Это то, что называется истинным языком ООП. Но C # не является чистым ООП из-за примитивных типов значений, оптимизаций чисел и строк.
enum Enumeration { V1, V2 }
struct Structure { string person; }
interface IClass { }
class Class : IClass { }
public static void Main()
{
string myStringInstance = "test";
int myIntegerInstance = 10;
var myEnumInstance = Enumeration.V1;
var myListInstance = new List<int>();
var myStructInstance = new Structure();
var myClassInstance = new Class();
var myInterface = (IClass)myClassInstance;
Console.WriteLine(myStringInstance is object);
Console.WriteLine(myIntegerInstance is object);
Console.WriteLine(myEnumInstance is object);
Console.WriteLine(myListInstance is object);
Console.WriteLine(myStructInstance is object);
Console.WriteLine(myClassInstance is object);
Console.WriteLine(myInterface is object);
Console.ReadKey();
}
> True
> True
> True
> True
> True
> True
> True
Теперь давайте посмотрим на различия между классом и структурой в низкоуровневом сгенерированном коде IL перед преобразованием в целевой машинный код:
struct Struct { public int Value; }
class Class { public int Value; }
public static void Main()
{
var myClass = new Class();
myClass.Value = 10;
Console.WriteLine(myClass.Value);
var myStruct = new Struct();
myStruct.Value = 20;
Console.WriteLine(myStruct.Value);
}
Вот как это выглядит:
.maxstack 2
.entrypoint
.locals init (
[0] class Program/Class myClass,
[1] valuetype Program/Struct myStruct
)
// Class @class = new Class();
IL_0001: newobj instance void Program/Class::.ctor()
IL_0006: stloc.0
// @class.Value = 10;
IL_0007: ldloc.0
IL_0008: ldc.i4.s 10
IL_000a: stfld int32 Program/Class::Value
// Console.WriteLine(@class.Value);
IL_000f: ldloc.0
IL_0010: ldfld int32 Program/Class::Value
IL_0015: call void [mscorlib]System.Console::WriteLine(int32)
IL_001b: ldloca.s 1
// Struct @struct = default(Struct);
IL_001d: initobj Program/Struct
// @struct.Value = 20;
IL_0023: ldloca.s 1
IL_0025: ldc.i4.s 20
IL_0027: stfld int32 Program/Struct::Value
// Console.WriteLine(@struct.Value);
IL_002c: ldloc.1
IL_002d: ldfld int32 Program/Struct::Value
IL_0032: call void [mscorlib]System.Console::WriteLine(int32)
Итак, предположим, что здесь, на этом уровне, нет реальной разницы между экземпляром объекта класса и экземпляром объекта структуры, потому что компилятор выполняет работу по обработке их в соответствии с их полом. И чтобы они имели поведение ссылочного типа или типа значения. В противном случае там, в сборке, больше нет никакой разницы, кроме случаев, когда это необходимо, но все это указатели. Практически все, что касается случаев памяти, по сути, через регистры процессора.
newobj
initobj
Как мы видим, класс или структура, это object
, обрабатывается двумя способами, но так же, как на двухполосной дороге.
Об объектах и экземплярах
Термины объект и экземпляр можно рассматривать как синонимы, но на самом деле они не являются синонимами с точки зрения скрупулезной терминологии. объект - это конкретная материализация типа (концепции или идеи) в реальном мире (виртуальный компьютерный мир, следовательно, физическая память). Экземпляр - это скорее ментальное существование этого объекта в человеческом разуме, следовательно, в программном коде. Итак, эти слова являются синонимами, но:
объект (существование) - это экземпляр (присутствие) типа (мысли).
В управляемом коде C # .NET указатель отсутствует. Указатели не являются объектами. Указатели - это адреса объектов, хранящихся в памяти. В C # мы используем ссылки, которые являются скрытыми указателями, чтобы забыть управлять ими. Указатель - это просто адрес ячейки памяти, как в городе. Мы могли бы сказать, что они являются объектами, но не в смысле объектов в ООП: эти указатели через ссылки позволяют нам создавать, манипулировать и уничтожать объекты, которые мы используем для создания приложений, которые запускаются на машине для приема данных, обрабатывать данные и выводить данные и / или управлять другим устройством.
В ООП все является объектом: en.wikipedia.org/wiki/Object_(computer_science) а>.
объект - это экземпляр введите.
Слова объект и экземпляр можно считать синонимами, но на самом деле они не являются синонимами с точки зрения скрупулезной терминологии. Объект - это конкретная материализация типа, концепции или идеи в реальном мире, в физической памяти. Пример - ментальное существование этого объекта в человеческом разуме, в программном коде. Итак, эти слова являются синонимами, но объект (существование) является экземпляр (наличие) введите (мысль).
Слова тип и класс или структура не являются синонимами. Можно считать синонимами объект и экземпляр, но не эти слова: класс, структура, перечисление или интерфейс являются типами. Например, стул и стол - это мебель, но стул и мебель - не синонимы. Можно представить, что слово тип является корневым классом (родительским concept) и слова class или struct ... с лингвистической точки зрения являются дочерними классами (дочерними концепциями). Так что они не синонимы: есть уровень абстракции, который имеет значение, как в дереве терминологии.
Экземпляр (данные в уме, которыми должен управлять код) типа структуры (статическое определение) - это объект (в памяти компьютера) .
Ответы на фундаментальные вопросы можно найти, изучив основы вплоть до Intel. Чтобы понять мотор машины, нам нужно открыть капот, а не разрезать руль, шины или кресла. Чтобы понять, что лежит в основе виртуального .NET, нам нужно изучить сам ЦП, и это увлекательно, иначе мы можем легко потерять время и неправильно понять вещи из-за путаницы и бессмысленности - то же самое для C #, основанного на теории ООП.
Иногда источник знаний в Интернете и в книгах может быть частичным или вводящим в заблуждение из-за ошибок, недосмотра, недопонимания, путаницы или незнания. Следовательно, важно начинать с небольшого числа источников с несколькими экспертами, например, с одного или двух надежных и авторитетных источников, с основ, и книги или профессиональные курсы являются лучшими, а не разбросанными. Освоившись, мы можем расширить поле и области и не бояться расхождений или противоречий.
О упаковке и распаковке
О упаковке / распаковке: переменная = объект в ООП, который является экземпляром структуры или класса, может быть упакован в object
и распакован из object
: Руководство по C #. По сути, распакованный тип значения - это object
, который не похож на object
(он уменьшен), чтобы его можно было оптимизировать для обработки нашими кремниевыми микропроцессорами, поэтому в коде IL и следовательно, в целевом машинном коде. В штучной упаковке этот тип значения представляет собой полноценный объект как таковой, помещенный в целую коробку и уже не дешевый. Тип значения в штучной упаковке используется как полный объект без оптимизации и отдельного поведения: теперь это ссылка, которой мы манипулируем, чтобы получить доступ к встроенному значению в исходном классе.
Неупакованное значение - это само значение, то есть сама ячейка памяти, если целое число, в памяти RAM и / или регистре ЦП, равном x32 или в настоящее время x64 (здесь одна ячейка). Значение в рамке - это ссылка на полный экземпляр объекта. встраивание этого значения (много ячеек). В распакованном виде манипулируют без использования всего, но в коробках его используют. Таким образом, последний работает медленнее и больше. Но яблоко остается яблоком. Например, если для метода требуется, чтобы экземпляр объекта был типа Object
, мы должны упаковать целое число, потому что он принимает только корневой тип всех.
Это означает, что бокс принимает оптимизированный, т.е. не чистый объект, например целочисленное значение (одна ячейка памяти), для создания полного объекта Int32
. Таким образом, эта память с одной ячейкой в стеке назначена свойству int
нового Int32
объекта в куче.
Разве бокс и распаковка - это не особый случай прямого кастинга?
Мы называем это упаковкой и распаковкой, потому что после упаковки в тип object
мы можем распаковать без ошибки преобразования типа компилятора, поскольку любое несоответствие типа будет возникать во время выполнения.
Из поля OpCodes.Box:
Преобразует тип значения в ссылку на объект (тип O).
Переходное поведение стека в последовательном порядке:
- Тип значения помещается в стек.
- Тип значения извлекается из стека; Операция с коробкой выполняется.
- Ссылка на объект для результирующего упакованного типа значения помещается в стек.
Тип значения имеет два отдельных представления в Common Language Infrastructure (CLI):
- «Необработанная» форма, используемая, когда тип значения встроен в другой объект или в стек.
- «Упакованная» форма, в которой данные в типе значения упакованы (упакованы) в объект, чтобы он мог существовать как независимый объект.
Инструкция бокса преобразует «необработанный» (распакованный) тип значения в ссылку на объект (тип O). Это достигается путем создания нового объекта и копирования данных из типа значения во вновь выделенный объект. valTypeToken - это токен метаданных, указывающий тип типа значения в стеке.
С точки зрения материальной архитектуры машинного кода, зависящей от микропроцессора типа Intel, это не что иное, как использование указателя памяти после выполнения всех указанных обработок.
Вот еще один пример:
int valueInt = 10;
double valueDouble = (double)valueInt;
object instance = (object)valueInt;
int value = (int)instance;
Код, сгенерированный IL:
.method private hidebysig static
void Test () cil managed
{
.maxstack 1
.locals init (
[0] int32 valueInt,
[1] float64 valueDouble,
[2] object 'instance',
[3] int32 'value'
)
// int num = 10;
IL_0001: ldc.i4.s 10
IL_0003: stloc.0
// double num2 = num;
IL_0004: ldloc.0
IL_0005: conv.r8
IL_0006: stloc.1
// object obj = num;
IL_0007: ldloc.0
IL_0008: box [mscorlib]System.Int32
IL_000d: stloc.2
// int num3 = (int)obj;
IL_000e: ldloc.2
IL_000f: unbox.any [mscorlib]System.Int32
IL_0014: stloc.3
IL_0010: ret
}
Из поля OpCodes.Unbox:
Преобразует упакованное в коробку представление типа значения в его распакованную форму.
Переходное поведение стека в последовательном порядке:
- Ссылка на объект помещается в стек.
- Ссылка на объект извлекается из стека и распаковывается в указатель типа значения.
- Указатель типа значения помещается в стек.
Тип значения имеет два отдельных представления в Common Language Infrastructure (CLI):
- «Необработанная» форма, используемая, когда тип значения встроен в другой объект.
- «Упакованная» форма, в которой данные в типе значения упакованы (упакованы) в объект, чтобы он мог существовать как независимый объект.
Инструкция unbox преобразует ссылку на объект (тип O), упакованное в коробку представление типа значения, в указатель типа значения (управляемый указатель, тип &), его распакованную форму. Предоставляемый тип значения (valType) - это маркер метаданных, указывающий тип типа значения, содержащегося в упакованном объекте.
В отличие от Box, который требуется для создания копии типа значения для использования в объекте, unbox не требуется для копирования типа значения из объекта. Обычно он просто вычисляет адрес типа значения, который уже присутствует внутри упакованного объекта.
Поскольку классы и структуры на самом деле одно и то же, конечно, они управляются по-разному, но представляют собой только ссылки и скрытые ссылки (указатели скрытой и скрытой-скрытой памяти, чтобы забыть управлять ими, а также доступ и использование, и делегировать это CLR), упаковка и разделение типов-значений и типов, не являющихся значениями, по существу одинаковы на этом низком уровне работы, поэтому код IL не делает различий между ними.
О ООП
Все это: .NET, C #, ООП, кастинг, бокс, распаковка ... это просто high- уровень языка лучше, чем машинный код, чтобы люди могли делать что-то лучше и проще, но сложнее и мощнее за меньшее время.
Мы должны помнить, что объект (дерево) может означать две вещи: экземпляр объекта в терминах ООП (завод) и корень C # для всех классов / структур / перечислений object
(граф). Но на самом деле это одно и то же, потому что все это object
на высшем уровне абстракции. Экземпляр объектов типа, являющегося ссылочным типом или типом значения, в обоих случаях является объектами. Его верхний тип object
: структура, класс и перечисление имеют тип object
. Всегда. Мы проверили это по коду и посмотрим, что является правдой.
В C # .NET OOP все объекты относятся к типу Object
class, и любая структура на самом деле является классом, особым классом: для IL это подкласс Object. Также любой интерфейс - это класс, особый класс: для IL это подкласс Object. Это сказано упрощенно.
Написав Object
, мы гарантируем, что говорим о типе корневого класса, который является предком всех типов .NET (классов, структур, перечислений, чисел). Когда мы говорим об объектах, мы имеем в виду экземпляр типа, принадлежащий этому корневому классу System.Object. Также типы объектов могут быть ссылками или типами значений: именно так компилятор управляет особыми случаями, поведением и оптимизацией ... Таким образом, этот комментарий вводит в заблуждение. Забудь это.
В ООП все является объектом. Это теория. Даже типы значений - это объекты, особенные по сравнению с другими классами. Все объясняется в двух экземплярах. Невозможно понять природу таких фундаментальных низкоуровневых объектов, как память, так и кодирование, без изучения этой теории и того, как работает материнская плата. На мой взгляд, невозможно без путаницы и вечных одних и тех же вопросов. Это похоже на попытку понять, что такое звезды, без изучения атомов.
В ООП все является объектом. Мы манипулируем объектами, которые имеют свойства или атрибуты, а также операции или методы. Даже в не-ООП, например, в структурированном и функциональном. В конце концов, все является объектом, независимо от его специализированного типа. Самый маленький объект, компьютерный атом, - это ячейка памяти и битовый блок. В эпоху кремниевых микропроцессоров, превышающую нули и единицы, самый маленький объект, который может сохранить компьютер, определяется размером его регистра: 8, 16, 32, 64 ... бит. Это базовый объект: байтовое слово dword qword ... Все в порядке.
Объект (объект является экземпляром класса) типа ValueType относится к классу, который наследуется от object
класса C #. Таким образом, все это класс C #, даже интерфейсы (в IL).
Что это, если не объект? В жизни и во Вселенной все является объектом, движением, построением, взаимодействием, эволюцией, разрушением ... Любое событие, связанное с явлением, требует физической поддержки, и эта поддержка называется объектом, сущностью явления (концепции и законы). . Ничего не существует без материи. Те, кто говорит иначе, просто лжецы. Итак, если тип-значение, интеграл / структура / str, то есть на верхнем уровне класс, известный как объект, иначе что это такое? Дух? Но дух есть материя: объект, живой (созданный и движущийся), а также мертвый (он не движется и одет).
Это делает теория ООП. Это заявили те, кто разработал эту теорию. Я просто согласен. То же самое и с Теорией клетки, которая утверждает, что вся жизнь происходит из клетки (ДНК / РНК / Organites) и не что иное, как законы, такие как гравитация.
В ООП все равно object
= Object
, даже в C #, где все является объектом типа класс, даже целые типы, структуры, числа и перечисления, а также строки. Ничего больше. На этом уровне абстракции не имеет значения, какие нюансы мы привносим в типы объектов.
В отличие от этого, на низком уровне, в виртуальной сборке IL и в машинном коде CPU-ASM, числа представляют собой простые байтовые значения во внутренних регистрах ЦП, поэтому они не являются объектами ООП ... Но такое рассмотрение, не зная, что насчет нас call сбивает с толку, потому что C # манипулирует объектами, все является объектом, даже после того, как оптимизация компилятора сделана, в отличие от Haskell или Smalltalk, если я помню и не говорю об этих истинных и чистых языках ООП.
DotNet - это не чистое ООП. Например, когда мы меняем значение целого числа, код IL изменяет содержимое ячейки по адресу, зарезервированному для этого значения. Он использует тот же адрес. Он просто делает то, что станет слабаком MOV addr, 10
. Он не создает копию с использованием другой ячейки или объекта, помещая в корзину старую ячейку или объект.
Что касается литералов, их нельзя рассматривать как объекты, поскольку они жестко запрограммированы в двоичном файле EXE. Работающий машинный код загружает буквальное значение (или его адрес, который будет связан с новым созданным объектом) из данных -segment в регистре и / или в адресе зарезервированной ячейки переменной, когда мы пишем int a = 10;
: 10 находится в сегменте данных EXE, загружаемом при запуске в память. Это не объект в терминах ООП: это просто несколько необработанных смежных байтов (целые числа, строки, массивы целочисленных типов): литералы не являются переменными, и никакие переменные не применяются к литералам, которые являются чистые необработанные данные без какой-либо абстракции или инкапсуляции.
.maxstack 1
.locals init ( [0] string str )
// string str = "This a literal test string for Stack Overflow!";
IL_0001: ldstr "Test"
IL_0006: stloc.0
// Console.WriteLine(str);
IL_0007: ldloc.0
IL_0008: call void [mscorlib]System.Console::WriteLine(string)
Эта инструкция IL в сегменте кода загружает это буквальный тест ... необработанные байты хранится в двоичном EXE-файле в экземпляре объекта str
a > создан и имеет тип string и на который ссылается указатель адреса памяти в стеке в позиции 0, и тогда эта локальная ссылка будет передано в метод консоли.
Вот сгенерированный компилятором дамп EXE, вагоны необработанных байтов, хранящиеся в сегменте данных, загружаемые при запуске процесса и используемые для создания нового экземпляра строки, как при использовании сканера для создания файла изображения:
Необработанные байты файла не являются объектами как таковые, рассматриваемые в ООП: они становятся объектами, когда экземпляры создаются после запуска приложения, для загрузки предопределенных данных или для обработки файлов. Это просто необработанные байты до запуска программы, а не объекты, пока нет.
Поэтому я рекомендую вам изучить основы этой теории ООП: абстракцию, инкапсуляцию, наследование и полиморфизм.
А также основы компьютеров на базе кремниевых микропроцессоров на материнской плате с некоторой памятью.
И если вы спросите меня, что является предком объекта ... ТАК :)
Предыдущие и следующие ссылки предназначены только для информации и демонстрации. Некоторые из них заслуживают доверия, другие могут содержать ошибки, противоречия или незнание по предмету, а также мнения, истинные или ложные, которые иногда трудно воплотить в реальность.
Также имейте в виду, что я мог неправильно истолковать и допустить неточности или даже недостатки, тем более, что я не очень хорошо говорю по-английски, не на моем родном языке, и у меня нет устных навыков, и мои воспоминания на ассемблере стары, а в старых компьютерах раньше эпоху x64, и что я не слишком много инвестировал в исследование IL / CLR, но то, что я объяснил, в основном, это так, в значительной степени.
ООП, абстракция, инкапсуляция и многое другое
Ищете чисто объектно-ориентированный язык
Разница между чисто объектно-ориентированным и объектно-ориентированным языком
Что такое чистый объектно-ориентированный язык в контекст DCI?
Что такое концепции ООП?
Что такое абстракция в C #?
Как выбрать между модификаторы публичного, частного и защищенного доступа?
Что такое полиморфизм?
В чем разница между интерфейсом и классом?
В чем разница между структурой и классом в .NET?
Почему методы возвращают только один вид параметра в нормальных условиях?
Литералы и неизменяемые
Как хранятся целочисленные литералы?
Почему числовые типы C # неизменяемы?
Изменяемый и неизменяемый класс в C #
Общие сведения о неизменяемости строк в C #
Неизменяемые объекты в C #
В чем разница между изменяемым и неизменяемая строка в C #?
Являются ли типы значений изменяемыми или неизменяемыми в C #?
Что такое изменяемые классы. Как мы можем создать изменяемый и неизменяемый класс на C #
Упаковка и распаковка
Зачем нам нужна упаковка и распаковка на C #?
Что такое настоящий использование бокса и распаковки?
Упаковка и распаковка в C #
C # | Бокс и распаковка
Взгляните на внутренности бокса в CLR
Как бокс и распаковка работают на самом низком уровне а>
Память, куча и стек
c # - что происходит в памяти при создании объектов?
Значения объявления, создания экземпляра, инициализации и присвоения объекта
Как хранятся целочисленные литералы?
C # Как сохранить строку
Использует ли new в структуре разместить его в куче или стеке?
Ссылки на эти объекты в стеке или на Куча?
Поля класса, хранятся ли они в стеке или куча?
Распределение памяти для переменной, объявленной в классе
Каким образом структура виртуальный метод экземпляра определяется с помощью объекта типа в куче?
Каким образом куча и стек работают для экземпляров и членов структуры в C #?
Где находится переменная типа значения - которая возвращается ref - live? Стек или куча?
Распределение памяти: стек против кучи?
Распределение памяти статического класса, где она хранится C #
Как будет выглядеть память для этого объекта?
Операционная система, ЦП и IL
Руководство по операционной системе
Книга концепций операционной системы
Разработчик программного обеспечения для архитектур Intel® 64 и IA-32 Руководства
.NET через CLR
Программирование MSIL 1
Программирование MSIL 2
Программирование MSIL
Подробнее о MSIL
person
Olivier Rogier
schedule
19.05.2021
ValueType
иObject
могут вызываться для типов значений. По этому определению типы значений являются объектами. Второе значение взято из спецификации C #, которая явно ссылается на экземпляры ссылочных типов как на объекты, за исключением типов значений. Оба значения являются действительными точками зрения, хотя в отношении типов значений они приходят к противоположному выводу. Третья точка зрения заключается в том, что упакованный тип значения является объектом, а необработанное значение - нет. - person ToolmakerSteve   schedule 21.01.2021