2014-03-26 3 views
3

Я читаю следующий блог Эрик Липперт: The truth about Value typesразница между ссылочными типами и ссылок

В этом он упоминает есть 3 вида значений в открытии:

  1. Instance типов значений

  2. Instance ссылочных типов

  3. Ссылки

    Неполный. Как насчет ссылок? Список литературы не являются ни типы значений, ни экземпляры ссылочных типов, но они являются значениями ..

Таким образом, в следующем примере:

int i = 10; 
string s = "Hello" 

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

ответ

4

Итак, что же такое третий тип, ссылки и как мы его получаем?

Переменная s - это переменная, которая содержит значение ссылки. Это значение является ссылкой на строку (со значением "Hello") в памяти.

Чтобы сделать это более ясным, что у вас есть:

string s1 = "Hello"; 
string s2 = s1; 

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

3

Поля и переменные ссылочного типа, такие как ваш s, являются ссылками на экземпляр ссылочного типа, который живет в куче.

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

+0

Вы уверены, что используете слово Heap ??? – user2711965

+0

@NewHire er ... Да? Управляемая куча. Вы думаете иначе? –

+0

@MarcGravell: «Это просто неверно, что выбор того, использовать ли стек или кучу, имеет принципиальное значение в отношении того, что хранится вещь» - из [блога] Эрика Липперта (http: //blogs.msdn .com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx) – user2711965

0

Ссылка не является действительно третьим типом. Это на самом деле указатель, который ссылается на конкретный экземпляр объекта. Посмотрите на этот пример:

class MyClass 
{ 
    public string Str { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     int a = 1; 
     int b = 2; 
     int c = 3; 
     var myObj = new MyClass 
     { 
      Str = "Whatever" 
     }; 

     Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str); 
     MyFunction(a, ref b, out c, myObj); 
     Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str); 

     Console.ReadLine(); 
    } 

    static void MyFunction(int justValue, ref int refInt, out int outInt, MyClass obj) 
    { 
     obj.Str = "Hello"; 
     justValue = 101; 
     refInt = 102; 
     outInt = 103; // similar to refInt, but you MUST set the value of the parameter if it's uses 'out' keyword 
    } 
} 

Вывод этой программы:

1;  2;  3;  Whatever 
1;  102; 103; Hello 

Фокус на MyFunction:

Первый параметр мы переходим является простой INT, который является значением тип. По умолчанию типы значений клонируются при передаче в качестве параметра (создается новый экземпляр). Вот почему значение «а» не изменилось.

Вы можете изменить это поведение, добавив ключевое слово 'ref' или 'out' в параметр.В этом случае вы фактически передаете ссылку на этот самый экземпляр вашего int. В MyFunction значение этого экземпляра переопределяется. Here you can read move out ref and out

Последний пример - объект MyClass. Все классы являются ссылочными типами, поэтому вы всегда передаете их в качестве ссылок (не требуется специальных ключевых слов).

Вы можете думать о ссылке как об адресе в памяти компьютера. Байты по этому адресу составляют ваш объект. Если вы передадите его как значение, вы берете эти байты и передаете их функции. Если вы передадите его в качестве ссылки, вы передаете только адрес. Затем в вашей вызываемой функции вы можете читать байты с этого адреса или писать на этот адрес. Каждое изменение влияет на переменные вызывающей функции, поскольку они указывают на то же количество байтов в памяти компьютера. Это не совсем то, что происходит в .Net (он работает на виртуальной машине), но я думаю, что эта аналогия поможет вам понять концепцию.

Почему мы используем ссылки? Есть много причин. Один из них заключается в том, что передача большого объекта по значению будет очень медленной и потребует клонирования. Когда вы передаете ссылку на объект, независимо от того, насколько большой этот объект, вы пропускаете только несколько байтов, содержащих его «адрес» в памяти.

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

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

Смежные вопросы