0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C# 自分用メモ その1 Listは参照渡し(?)->クラスは「参照"型"」なのだそうです。

Last updated at Posted at 2024-06-21

1. はじめに

私はいい歳したC/C++屋さんなのですが、必要に迫られてC#を触っています。そんなこんなで「ん~これはハマりそうだな」と思った事を記録しておきます。自分用メモ。

2.コードその1

実行結果に"1"が表示されるので参照渡しかなぁと思った私。

Program.cs
using System;
using System.Collections.Generic;

namespace ListTest
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> testList = new List<int>();
            MyFunc(testList);

            System.Console.WriteLine(testList[0].ToString());
        }

        static void   MyFunc(List<int> aList)
        {
            aList.Add(1);
            return;
        }
    }
}

3.指摘を受けました(コードその2)

もし、「参照渡し」なのならばこのプログラムで「2」が表示されるはずなのですが、実際は「1」が表示されます。

Program.cs
static void Main(string[] args)
{
    List<int> aList = new ();
    aList.Add(1);
    MyFunc(aList);

    // 結果は"1"が表示される。なぜだ ?
    foreach (int x in aList)
    {
        Console.Write($"{x} ");
    }
    Console.WriteLine();
}

static void MyFunc(List<int> listA)
{
    List<int> listB = new();

    // listBに対する超複雑な処理のつもり
    listB.Add(2);
    // 途中でlistAのデータを見るかもしれないので
    // listAは最後まで壊さない

    // listAが参照渡しなら結果は2が表示されるはず
    listA = listB;
}

こういうことか、と。みんなハマってんだなぁ。
https://qiita.com/yutorisan/items/15e1b6bf21d70770de07

4.では関数引数の中身を壊したくない(値渡しにしたい)場合はどうするか

Program.cs
void MyFunc(List<int> ListA)
{
   List<int> ListB = new(ListA);

    // ごにょごにょ
}

なのだそうです

5. C++ではどうなるのか

で、C++であればコピーコンストラクタが働きますから「呼び出し元のaListの中身は変わらない」のです。いきなりハマってしまいました。やれやれ。

list5.cpp
#include <iostream>
#include <list>

void    MyFunc(std::list<int> list);

int main()
{
    std::list<int> aList;
    aList.push_back(1);
    MyFunc(aList);

    // 1 のみ表示される
    for (int x : aList) {
        std::cout << x;
    }
    std::cout << std::endl;
}

void    MyFunc(std::list<int> worklist)
{
    // この時点で aListとは別物
    worklist.push_back(2);
}

6. 3の状況をC++で無理やり再現してみた(蛇足)

うわっ。気持ち悪いわ~。

list6.cpp
#include <iostream>
#include <list>

void    MyFunc(std::list<int>* pList);

int main()
{
    std::list<int> aList;
    aList.push_back(1);
    MyFunc(&aList);

    // 1 のみ表示される
    for (int x : aList) {
        std::cout << x;
    }
    std::cout << std::endl;
}

void    MyFunc(std::list<int>* pListA)
{
    std::list<int> listB;
    // listBに対する超複雑な処理のつもり
    listB.push_back(2);
    // 途中で pListA のデータを見るかもしれないので
    // plistA は最後まで壊さない

    // なんだこの違和感わ orz
    pListA = &listB;
}

コメント頂いた皆様に感謝申し上げます。

0
1
18

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?