путаница с типом значения и ссылочным типом в c # - PullRequest
2 голосов
/ 01 сентября 2010

Я немного сбит с толку насчет параметров. Когда нам нужно использовать ссылочный параметр и когда нужно использовать параметры типа значения при программировании с помощью методов / функций в c #?

Ответы [ 5 ]

16 голосов
/ 01 сентября 2010

Вы должны быть очень ясно о различии между ссылочными типами и типами значений и параметрами "по значению" и "ссылочными" параметрами.

У меня есть статьи на обе темы:

При взаимодействии несколько взаимодействуютпараметр «по значению», который является ссылочным типом: в этом случае значение, которое копируется по значению, является самой ссылкой;вы все еще можете изменить объект, на который ссылается ссылка:

void SomeMethod(StringBuilder x)
{
    x.Append("Modified");
}
...

StringBuilder builder = new StringBuilder();
SomeMethod(builder);
Console.WriteLine(builder.ToString()); // Writes "Modified"

Обратите внимание, что это не то же самое, что семантика передачи по ссылке ... if SomeMethodбыли изменены, чтобы включить:

x = null;

, тогда не сделает переменную builder нулевой.Однако, если вы также изменили параметр x на ref StringBuilder x (и изменили код вызова соответствующим образом), то любые изменения на x (например, установив его на ноль) будут будет замечено вызывающим абонентом.

При разработке собственного API я настоятельно рекомендую вам почти использовать ref или out параметры.Они могут быть полезными время от времени, но обычно они указывают на то, что вы пытаетесь вернуть несколько значений из одного метода, что часто лучше сделать с типом, специально инкапсулирующим эти значения, или, возможно, Tuple введите, если вы используете .NET 4. Конечно, есть исключения из этого правила, но это хорошая отправная точка.

0 голосов
/ 01 сентября 2010

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

using System.Collections.Generic;
using System.Diagnostics.Contracts;

class Program
{
    static void Main(string[] args)
    {
        var list = new List<int>(new[] { 1, 2, 3, 4 });

        MakeItNull(list);
        Contract.Assert(list != null);

        MakeItRealNull(ref list);
        Contract.Assert(list == null);
    }


    static void MakeItNull(List<int> list)
    {
        list = null;
    }

    static void MakeItRealNull(ref List<int> list)
    {
        list = null;
    }
} 
0 голосов
/ 01 сентября 2010

Лучшая статья на эту тему:

C # Куча (ing) и стек (ing) в .NET: Часть I

Есть четыре части.

0 голосов
/ 01 сентября 2010

Когда вы отправляете параметр типа Value, то внутри функции / метода отправляется внутренняя копия исходной переменной. Поэтому, если вы измените значение внутри этой функции, исходное значение переменной (с нашей стороны, где она объявлена) останется без изменений.

Когда вы отправляете параметр типа Reference, функция воспроизводит непосредственно исходное значение этой переменной. Это потому, что вы отправляете только ссылку на память этой переменной в вашу функцию.

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

0 голосов
/ 01 сентября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...