Список <int>в c # - PullRequest
       15

Список <int>в c #

6 голосов
/ 09 июля 2010

Я не могу понять логику, стоящую за List<int>, поскольку она нарушает некоторые из основных правил.

List<int> должен иметь тип значения, а не ссылочный тип.

  1. List<int> должно быть передано ключевым словом ref, если его значение необходимо сохранить между вызовами функций.Таким образом, это означает, что он отображает поведение типа значения, подобное int.
  2. Но List<int> должен быть инициализирован новым оператором.Также List<int> также может быть нулевым.Это подразумевает поведение ссылочного типа.

Обнуляемый тип отличается тем, что его не нужно инициализировать оператором new.

Я вижу здесь что-то не так?

EDITED-

Я должен был разместить код в самом оригинальном вопросе.Но здесь следует -

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ListTest d = new ListTest();
            d.Test();
        }
    }

    class ListTest
    {
        public void  ModifyIt(List<int> l)
        {
            l = returnList();
        }

        public void Test()
        {
            List<int> listIsARefType = new List<int>();
            ModifyIt(listIsARefType);
            Console.WriteLine(listIsARefType.Count); // should have been 1 but is 0
            Console.ReadKey(true);
        }

        public List<int> returnList()
        {
            List<int> t = new List<int>();
            t.Add(1);
            return t;
        }
    }
}

Ответы [ 9 ]

28 голосов
/ 09 июля 2010

Список должен иметь тип значения, а не ссылочный тип.

Неверно! int - тип значения.List<int> является ссылочным типом.

7 голосов
/ 09 июля 2010

Я думаю, что вы ошиблись в своей первой пуле. Общий объект List определенно является ссылочным типом (в куче, а не в стеке). Не уверен, почему вы думаете, что должны пройти через ref. Это печатает "2", как должно:

namespace ConsoleApplication1 {
   class Program {
      static void Main(string[] args) {
         List<int> listIsARefType = new List<int>();
         ModifyIt(listIsARefType);
         ModifyIt(listIsARefType);
         Console.WriteLine(listIsARefType.Count); // 2!
         Console.ReadKey(true);
      }

      static void ModifyIt(List<int> l) {
         l.Add(0);
      }
   }
}
6 голосов
/ 09 июля 2010

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

В примере кода, который вы опубликовали, вы передаете ссылку объекту List<int> с значением . Это означает, что вы можете изменить объект, на который указывает ссылка, и вызывающий код увидит эти изменения. Однако сама ссылка передается по значению, поэтому, если вы измените ссылку так, чтобы она указывала на другой объект в целом, вызывающий код не увидит изменений.

Когда вы используете ключевое слово ref, вы передаете ссылку непосредственно по ссылке. Это означает, что вы можете не только изменить объект, на который указывает ссылка, но вы также можете изменить саму ссылку.

Рассмотрим этот пример:

class Program
{
    static void Main()
    {
        int foo = 0;
        DoSomething1(foo);
        Console.WriteLine(foo); // Outputs 0.

        DoSomething1(ref foo);
        Console.WriteLine(foo); // Outputs 1.

        var bar = new List<int>();
        DoSomething2(bar);
        Console.WriteLine(bar.Count); // Outputs 1.

        DoSomething2(ref bar);
        Console.WriteLine(bar.Count); // Outputs 0.
    }

    // Pass by value.
    static void DoSomething1(int number)
    {
        // Can't modify the number!
        number++;
    }

    // Pass by value.
    static void DoSomething1(ref int number)
    {
        // Can modify the number!
        number++;
    }

    // Pass reference by value.
    static void DoSomething2(List<int> list)
    {
        // Can't change the reference, but can mutate the object.
        list.Add(25);
    }

    // Pass reference by reference.
    static void DoSomething2(ref List<int> list)
    {
        // Can change the reference (and mutate the object).
        list = new List<int>();
    }
}
2 голосов
/ 09 июля 2010

Не думайте об этом как List<int> думайте об этом так, как это было написано List<t>.

Список является универсальным классом . Это не структура. Это универсальный класс, который может работать с типами значений и ссылочными типами.

2 голосов
/ 09 июля 2010

List<int> действительно является ссылочным типом.Но элементы, содержащиеся в списке, являются типами значений.

Обнуляемые типы реализуются как структуры (struct Nullable<T> where T : struct) и, следовательно, являются типами значений.Причина, по которой вы можете просто написать

int? i = 3;

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

Nullable<Int32> i = new Nullable<Int32>(3);

Чтобы лучше понять различия между типом значения и семантикой ссылочного типа, я бы порекомендовал вам прочитать статью Джона Скита на эту тему, которая поможет вам с большим количеством иллюстративного примера кода:

Джон Скит: Передача параметров в C #

1 голос
/ 09 июля 2010

A List - это общий ссылочный тип, вы используете его с типом значения int.Но это все еще ссылочный тип.

0 голосов
/ 31 января 2014

В методе ModifyIt (), когда вы пишете 'l = returnList ()';'l' теперь указывает на другое место в памяти, чем на listIsARefType в вашем методе Test ().По сути, написав 'l' '=' что-то, вы разорвали связь между 'l' и 'listIsARefType'.Чтобы сохранить ссылку (то есть убедиться, что оба объекта, 'l' и 'listIsARefType' указывают на одно и то же место в памяти), вам нужно либо работать только с объектом 'l' (напримервызывая функцию объекта), или используйте ключевое слово ref в параметре метода ModifyIt ().

0 голосов
/ 09 июля 2010

В дополнение к ошибочным предположениям, рассмотренным в других ответах, вы говорите:

List<int> должен быть инициализирован новый оператор ... Это подразумевает поведение ссылочного типа.

Нет, в C # оператор new - это просто синтаксис для вызова конструктора типа. Используется как для справочных, так и для пользовательских типов значений (struct с).

0 голосов
/ 09 июля 2010

List<int> является ссылочным типом.И его не нужно передавать как ссылку.

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

...