Несколько вопросов о языке C # - PullRequest
1 голос
/ 21 мая 2010

1) Что такое int? Чем он отличается от struct System.Int32? Я понимаю, что первый является псевдонимом C # (typedef или #define эквивалент) для типа CLR System.Int32. Это понимание правильно?

2) Когда мы говорим:

IComparable x = 10;

Это как сказать:

IComparable x = new System.Int32();

Но мы не можем new структуру, верно?

или в C, как синтаксис:

struct System.In32 *x;
x=>someThing = 10;

3) Что такое String с заглавными буквами S ? В Reflector я вижу, что это класс sealed String, который, конечно, является ссылочным типом, в отличие от System.Int32 выше, который является типом значения.

Что такое string с некапитализированным s? Это также псевдоним C # для этого класса?

Почему я не вижу определения псевдонимов в Reflector?

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

Person p = new Customer();
p.Name = "Water Cooler v2"; // legal because as Name is defined on Person.

но

// illegal without an explicit cast even though the backing 
// store is a Customer, the storage location is of type 
// Person, which doesn't support the member/method being 
// accessed/called.
p.GetTotalValueOfOrdersMade();

Теперь с этим выводом рассмотрим следующий сценарий:

int i = 10;

// obvious System.object defines no member to 
// store an integer value or any other value in. 
// So, my question really is, when the integer is 
// boxed, what is the *type* it is actually boxed to. 
// In other words, what is the type that forms the 
// backing store on the heap, for this operation?
object x = i;

Обновление

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

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

Ответы [ 4 ]

5 голосов
/ 21 мая 2010
  1. int - псевдоним для System.Int32. Типы идентичны.

  2. IComparable x = 10 будет похоже на запись var i = 10; IComparable x = i. Компилятор выбирает тип константы, который он считает наиболее вероятным, а затем выполняет неявное преобразование в IComparable.

  3. string - псевдоним для System.String, аналогично # 1. Вы не можете увидеть определения псевдонимов в Reflector, потому что псевдоним является частью компилятора C #, а не самой .NET Framework. (Например, в VB.NET все по-другому.)

  4. Целочисленное целое или другой тип значения является ссылкой на значение. Вы, вероятно, могли бы думать об этом как о указателе с некоторой информацией о типе. Фактический тип поддержки, однако, просто System.Object.

2 голосов
/ 21 мая 2010

Я отвечу только на вопросы 2 и 4, потому что, похоже, что на остальные уже есть удовлетворительный ответ.

Сначала давайте посмотрим на этот код из вашего вопроса:

int i = 10;
object x = i;

Теперь, для меня это звучит так, как будто вы обдумываете это Да, это правда, что тип System.Object не содержит ни одного члена, который представлял бы int, который был помещен здесь. Но это не делает этот случай чем-то отличным от другого кода, который вы выложили, и вы, кажется, прекрасно понимаете:

Person p = new Customer();
p.Name = "Water Cooler v2";

В этом случае класс Customer является производным от класса Person. Существуют поля, методы и т. Д., Принадлежащие Customer, которые не видны из контекста Person, но Customer - это a Person. Точно так же, System.Int32 (что то же самое, что и int, как указывали другие) происходит от System.Object. Просто есть операции, которые вы можете выполнить на int, которые не видны из контекста object - например, выполнение сложения и т. Д. Но int - это an object.

Итак, ответ на вопрос "что на самом деле помещается в кучу?" (кстати, куча, являющаяся деталью реализации CLR) на самом деле довольно проста: туда ставится int.

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

Но мы не можем new структуру, верно?

На самом деле, это неточно. Что делает ключевое слово new? Похоже, вы думаете в терминах C ++ и предполагаете, что если тип размещен в стеке (опять же, обратите внимание на детали реализации), то использование ключевого слова new не имеет смысла. Но в C # new в основном означает, что вы вызываете конструктор типа. И типы значений (структуры) имеют конструкторы, как и ссылочные типы (классы); так что да, эта строка:

IComparable x = 10;

фактически совпадает с:

IComparable x = new System.Int32(10); // if System.Int32 had a public
                                      // parameterized constructor
                                      // (which it doesn't, probably
                                      // because that would just
                                      // confuse people)

Теперь позвольте мне задать вам вопрос: в чем важная разница между типами значений и ссылочными типами в .NET? Если ваш ответ включает какое-либо из слов «стек», «куча» или «выделенный», то, скорее всего, вы сосредоточены на неправильной вещи. Какое это имеет значение для нас, разработчиков, для размещения объектов (помимо подробностей, связанных с настройкой производительности)? На мой взгляд, важное различие заключается в том, что типы значений передаются по значению (копируются) в вызовах методов . Честно, вот и все. Вот что важно.

Когда вы смотрите таким образом, большая загадка бокса / распаковки на самом деле не так таинственна. Давайте посмотрим на этот код еще раз:

int i = 10;
object x = i;

Мы говорим, что в приведенном выше коде мы "упаковываем" целое число i в объекте x. Но что подразумевается под этим термином «бокс»? Это то же самое, что поместить значения в кучу? Как это может быть, если выделение кучи и стека является неопределенной деталью реализации?

Помните, что я говорил о типах значений. Важно, чтобы int был типом значения: когда вы передаете int методу, вы действительно передаете копию. Это поведение всех типов значений, аналогичное тому, как говорят все типы, производные от System.ValueType. Но обратите внимание, что System.Object не происходит от System.ValueType. Это наоборот. object является ссылочным типом.

Итак, "бокс" на самом деле означает, что вы берете объект, который в силу его типа всегда передается по значению, и приводите его к базовому типу (object) который передается по ссылке *.

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

  1. Все люди по умолчанию ездят на колесе обозрения.
  2. Жители Нью-Йорка, в частности, вместо этого едут на карусели.

Перед тем, как войти в парк, вы заполняете небольшую форму, классифицирующую себя. После подачи этой формы вы получите красный браслет, если вы из Нью-Йорка, или синий браслет.

Что если вы из Нью-Йорка, но хотите прокатиться на колесе обозрения? Все просто: вместо того, чтобы заполнять вашу классификацию как «житель Нью-Йорка», вы просто пишете «Персона». Бинго, они дают вам синий браслет, и вы в.

Ключевое различие, которое следует здесь сделать, заключается в том, что объекты могут делать и как они обрабатываются . Как я уже говорил несколько раз, System.Int32 происходит от System.Object, и поэтому вы можете привести int к object так же легко, как вы можете привести объект любого типа к типу. из которого это происходит. Все это ограничивает то, что вы можете делать с этим объектом, потому что доступны только методы, поля и т. Д. Базового класса. Ничего особенного там нет. Но , бросая int на object, вы меняете способ обработки . Точно так же, как приведение себя в примере тематического парка к «Персоне» - что-то менее конкретное, чем то, что вы есть на самом деле, «житель Нью-Йорка», или другими словами базовый тип - вы изменили способ вас лечили.

Имеет ли это смысл?


* Утверждение, что ссылочные типы «передаются по ссылке», возможно, не является строго точным утверждением и вызвало много недоразумений для многих разработчиков (более точное утверждение может быть «ссылки на ссылочных типов передаются значение"); для подробного обсуждения этой темы вам нужно поискать в другом месте.

1 голос
/ 21 мая 2010

1) Да. "int" - это просто псевдоним, который C # определяет для System.Int32.

2) Ваш первый ответ.

3) строка - это псевдоним C # для типа System.String. Поскольку почти у всех есть «использование системы»; в их программе вы можете использовать либо «строку», либо «строку».

4) Вы можете думать о нем как о int, хранящемся в поле ссылочного типа. Даже если тип поля виден только как «объект», среда выполнения знает, что внутри него есть int.

Вот почему ты не можешь написать:

int i = 10;
object x = i;
short j = (short) x; // this is an error because you can only unbox x as an int.

Многое из этого есть в справочнике по языку C # или в одной из вводных книг.

0 голосов
/ 21 мая 2010

1) int - псевдоним для структуры System.Int32. Вы можете определить любой псевдоним, который вы хотите для типа в C #. Для этого вам нужно использовать использование statment, аналогичное использованию statments, которое вы обычно импортируете в пространства имен. Например, если я хотел бы создать псевдоним для System.Int64 и назвать его номером, я бы написал следующее с использованием статистики в начале моего файла кода:

using number = System.Int64;

Затем, каждый раз, когда я использую псевдоним число в своем коде, компилятор и intellisense будут обрабатывать его точно как System.Int64.

2) Использовать конструктор System.Int32 по умолчанию так же, как присваивать целочисленную переменную 0.

IComparable x = new System.Int32();

точно так же, как код

IComparable x = 0;

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

Интересный факт: в C # не все происходит от объекта .

3) string является ключевым словом компилятора C # (как ключевое слово int), поэтому вы не можете увидеть его определение с помощью Reflector. Фактически, IL-код, сгенерированный компилятором, даже не существует этих псевдонимов, потому что они используются только компилятором во время процесса компиляции. После компиляции все ссылки string становятся System.String в вашем скомпилированном коде.

4) Ответ на этот вопрос слишком длинный, поэтому я предлагаю вам прочитать следующую статью: Представительство и идентичность

...