Семантика типов в Си и C#?
Сходство есть, но и различий достаточно. Указатель хранит адрес в памяти, который в общем-то доступен вам для чтения и записи. Вы можете любой int скастить в указатель и попытаться разыменовать его. Врядли ли вы получите от этого что-то полезное, но суть в том что вы МОЖЕТЕ это сделать. Указатель как тип данных лишь даёт вам удобное средство для адресации и типизированной работы с областью памяти.
Ссылка в .net - вещь значительно более высокоуровневая. Это скорее object identity, а не адрес в памяти. Ссылка не хранит непосредственно адрес объекта в управляемой куче, она хранит его номер, а конкретным адресом в памяти управляет сборщик мусора (так сделано потому, что сборщик имеет право перемещать объекты в памяти, если они явно не закреплены).
Как уже сказали выше, указатели в C# тоже есть, и они действительно хранят адрес. Но они доступны только в unsafe контексте и не являются средством для everyday-разработки.
Ссылки в C# концептуально связаны с объектным подходом, ссылка хранит идентификатор объекта и является "ключом" доступа к нему. Ссылка не может непосредственно ссылаться на типы-значения на уровне платформы .net, для этого нужно сначала выполнить boxing значения.
Сишкном указателю же без разницы, на что он указывает. Если говорить в контексте C++, то программист по сути сам даёт указателям на объекты семантику object identity.
Не совсем. Ссылка не может указывать чёрт знает куда, только на объект соответствующего типа или быть нулём(null). Добавочно ссылочный тип всегда проверяется на не равенство нулю при вызове из него метода. То есть внутри метода this == null всегда ложно. В С# есть и обычные указатели, но только в небезопасном режиме.