Ответ 1
Другие ответы здесь довольно хорошие, но я думаю, что они не понимают основные принципы. Это основные принципы, которые вы путаете, поэтому позвольте им обратиться к ним.
- Переменная - это место хранения, содержащее значение.
- Переменная связана с типом.
- Локальная переменная имеет имя.
So voidInt
, voidChar
, voidCharArray
, varInt
, varChar
и varCharArray
- все переменные, и все они имеют связанные с ними типы. Каждой переменной может быть присвоено значение этого типа или вывести значение этого типа в зависимости от того, записывается ли переменная или читается.
Хорошо, теперь что такое указатели?
- Тип имеет соответствующий тип указателя. (Обратите внимание, что в небезопасных С# только неуправляемые типы имеют соответствующие типы указателей.)
- Тип
void *
- это специальный тип указателя. - Указатель - это значение.
- Указатель типа
T*
может быть разыменован для получения переменной типаT
.T*
не должен бытьvoid*
. - Указатель может быть явно преобразован в любой тип интеграла или из него, хотя эти операции могут потерять информацию и зависят от деталей реализации.
- Любое значение указателя может быть неявно преобразовано в
void*
. - Любое значение
void*
может быть явно преобразовано в любое значение типа указателя.
А что такое var
в С#?
-
var
является "синтаксическим сахаром", который сообщает компилятору вывести тип переменной из initialzier, а не требовать, чтобы он был выписан.
А что такое "анонимные типы" на С#?
- Некоторые выражения в С# имеют тип, который не объявлен и не имеет имени; они известны как "анонимные" типы.
Итак, теперь мы можем посмотреть вашу программу и посмотреть, что делает каждая строка.
void * voidInt = (void *) 7;
voidInt
- это переменная типа void*
. Значением, назначенным ему, является преобразование целого числа 7 в указатель, что почти наверняка является указателем мусора для любой современной операционной системы. Этот код по сути бессмысленен.
Более разумный код:
int myInt = 7;
int* intPtr = &myInt;
void* voidInt = intPtr;
Это означает, что myInt
- это переменная, которая содержит значение 7
, intPtr
- переменная, которая содержит указатель; когда этот указатель разыменован, он генерирует переменную myInt
. voidInt
- это переменная, которая содержит любой указатель, а значение, считанное из intPtr
, является указателем. Итак, теперь voidInt
и intPtr
содержат указатель на переменную myInt
.
void * voidChar = (void *) 'F';
То же самое здесь. Символ F
обрабатывается как число и преобразуется в значение указателя, которое хранится в переменной. Это неразумно. Разумный код будет примерно таким:
char myChar = 'F';
void *voidChar = &myChar;
Но это имеет смысл:
void * voidCharArray = (void *) "AbcString";
Строковый литерал в С++ конвертируется в char*
, который является указателем на хранилище для первого символа, и этот указатель можно конвертировать в void*
.
Как насчет этого?
var varInt = 7;
var varChar = 'F';
var varCharArray = "AbcString";
Это просто приятный способ написать
int varInt = 7;
char varChar = 'F';
string varCharArray = "AbcString";
Каждая переменная имеет свой заданный тип, и каждое присваивание сохраняет значение этого типа в переменной.
Как насчет анонимных типов?
var anon = new { X = 123, Y = 456 };
Это делает переменную анонимного типа, где анонимный тип имеет два свойства X и Y как тип int
. Тип не имеет имени, поэтому нет способа записать тип объявления, поэтому var
должен использоваться.
Ключевое значение здесь - убедиться, что у вас есть понимание основ: указатели являются значениями, они могут быть разыменованы, и при этом создается переменная. Поскольку указатели являются значениями, они могут сами храниться в переменных типа указателя. Это почти не имеет отношения к var
, что является приятным способом в С#, чтобы заставить компилятор выполнить работу по выяснению того, какой тип должен иметь переменная.