51275


C#では`string`型は参照型なのでなのですがその参照型に`ref`を使うと内部的にはどのような処理になっているのでしょうか？`ref`は参照を渡すという意味なのですが参照型に参照を渡すとどうなるのでしょうか？実験してしてもエラーにもならずなおかつ実行内容を同じためどのような処理をしているかわかりません、教えてくれますでしょうか？

1,質問なのですがc++の `int a; &a`といった書き方の`&`も参照を渡してるという意味ですが  
それと大体同じなのでしょうか？

[code]

    static void Main(string[] args)
    {
        del_addS add = (ref string a, ref string b) =>
        {
            return a + b;
        };
    
        del_addS add2 = delegate (ref string x,ref string y)
        {
            return x + y;
        };
    
        del_add adds = delegate (string x, string y)
        {
            return x + y;
        };
    
        string aa = Console.ReadLine();
        string bb = Console.ReadLine();
    
        //string s = add(ref aa,ref bb);
        //string s = add2(ref aa,ref bb);
        string s = adds(aa,bb);
        Console.WriteLine(s);
    
    
    
        Console.ReadKey();
    }
    
[/code]


CC BY-SA 4.0
2018-12-16T12:38:56.123
51261
2018-12-17T01:15:13.897
2018-12-16T14:50:13.500
2238
question
c#
C# string型は参照型なのにrefをつけて関数に渡してもエラーにはならない理由


今のサンプルコードでは ref キーワードなしで十分です。  
ref キーワードの動きを理解するためには、以下のコードを実行してみてください。

[code]

    static void Main()
    {
        string a = "123";
        string b = "456";
    
        test1(a)
        test2(ref b);
    
        Console.WriteLine(a);
        Console.WriteLine(b);
    }
    
    static void test1(string s)
    {
        s = "789"; // 引数に代入しても呼び出し元には影響しない
    }
    
    static void test2(ref string s)
    {
        s = "789"; // refなので呼び出し元に対して影響を与える
    }
    
[/code]


CC BY-SA 4.0
2018-12-16T21:22:56.007
51271
2018-12-16T21:22:56.007
4684
51261
answer


参照型に `ref` をつけると違うオブジェクトを参照させることができます。

[code]

    class Class1 { }
    static void Test(ref Class1 r)
    {
        r = new Class1();
    }
    static void Main()
    {
        Class1 x = new Class1();
        Class1 y = x;
        Console.WriteLine(x.Equals(y)); // True
        Test(ref x);
        Console.WriteLine(x.Equals(y)); // False
    }
    
[/code]

既に [c](/questions/tagged/c "'c' のタグが付いた質問を表示") や
[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") に親しい人なら
[c#](/questions/tagged/c%23 "'c#' のタグが付いた質問を表示") の参照型は  
\- ソースコード上の参照型変数は、実際にはポインタ変数である  
\- ポインタしかないのだから `new` しないと実体はない  
\- [c#](/questions/tagged/c%23 "'c#' のタグが付いた質問を表示") のソースコード上の記述 `ref.member`
は、[c](/questions/tagged/c "'c' のタグが付いた質問を表示") /
[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") では `->` と書いてあるのと同じ  
と理解しておけばOKです。今回の質問に関してならば

1 参照型の `ref` なし引数は単にポインタ変数を引き渡すだけ

\--- C# ---

[code]

    void func(Class1 p)
    {
        p = new Class1(); // としても呼び出し元の仮引数は変わらない
    }
    
[/code]

\--- C++ ---

[code]

    void func(class1* p) {
        p = new class1(); // としても呼び出し元の仮引数は変わらない
    }
    
[/code]

2 「参照型の `ref` 」は「ポインタ変数へのポインタ」

\--- C# ---

[code]

    void Func2(ref Class1 pp)
    {
        pp = new Class1(); // 呼び出し元の仮引数が変わる
    }
    void Main()
    {
        Class1 p = new Class1();
        Func2(ref p);
    }
    
[/code]

\--- C++ ---

[code]

    void func2(class1** pp) {
        *pp = new class1(); // 呼び出し側の仮引数（の指す先）が変わる
    }
    int main() {
        class1* p = new class1();
        func2(&p);
    }
    
[/code]

理解に自信がないうちは参照型の `ref` は使わないのが吉。ほとんどの場合使わなくても何とかなります。


CC BY-SA 4.0
2018-12-17T01:15:13.897
51275
2018-12-17T01:15:13.897
8589
51261
answer