C#の実引数と、仮引数の関係はJavaに準じているが(参照値渡し)refキーワードを用いることで参照渡しを実現できる。

using System;
using System.Collections.Generic;

namespace DicLesson
{
    class MainClass
    {
        public static void Main(string[] args)
        {

            int x = 10;
            fuga(x);
            Console.WriteLine("main:x=" + x);
            fugaRef(ref x);
            Console.WriteLine("main:x=" + x);

            int[] arr = { 200, 300 };
            hoge(arr);
            Console.WriteLine("main:arr[0]=" + arr[0]);
            hogeRef(ref arr);
            Console.WriteLine("main:arr[0]=" + arr[0]);

            int[] arr2;
            //hogeRefの中で配列が割り当てられることがわかっていても初期化は必須
            //なので以下はエラー
            //hogeRef(ref arr2);

            //outを利用
            hogeOut(out arr2);
            Console.WriteLine(arr2[0]);//3

            //outは事前の宣言すら不要
            hogeOut(out int[] arr3);
            Console.WriteLine(arr3[1]);



        }
        //値渡し
        public static void fuga(int num)
        {
            num = num * 2;
            Console.WriteLine("inFuga:num=" + num);

        }
        public static void fugaRef(ref int num)
        {
            num = num * 2;
            Console.WriteLine("inFugaRef:num=" + num);

        }
        //参照値渡し(参照型)
        public static void hoge(int[] arr)
        {
            arr = new int[] { 3, 4, 5 };
            Console.WriteLine("inHoge:arr[0]=" + arr[0]);

        }
        //参照渡し(参照型)
        public static void hogeRef(ref int[] arr)
        {
            arr = new int[] { 3, 4, 5 };
            Console.WriteLine("inHogeRef:arr[0]=" + arr[0]);
        }

        //out
        public static void hogeOut(out int[] arr)
        {
            arr = new int[] { 3, 4, 5 };
            Console.WriteLine("inHogeOut:arr[0]=" + arr[0]);
        }
    

    }
}

このようにrefキーワードを用い参照渡しをすれば値を書き換えることができる。しかし以下のような問題もある。
1.ref引数に渡すには事前の初期化が必要
2.メソッドの中でref引数に値が渡されなくてもエラーにならない

メソッドの中で値を割り付けることがわかっている場合には1の処理は無駄となる。
そこでメソッドの中で値を割り付けることがわかっている場合はout キーワードを用いるとよい。

out キーワードを用いることにより初期化は不要となり、メソッド内で値の割付を行わなかった場合はコンパイルエラーとなる。

Q
outキーワードを用いて、int型の配列を受け取り、その中の最小値と最大値を変数に割り付けるメソッド作成し。
以下の処理を実現せよ。
整数をカンマ区切りで入力してください。
3,1,5,7,10[enter]
最小値1,最大値10

using System;
using System.Collections.Generic;
using System.Linq;

namespace DicLesson
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("整数をカンマ区切りで入力してください。");
            /*LINQを使うと超すっきり
            var data = Console.ReadLine().Split(',').Select(int.Parse).ToArray();
            */
            var strArr = Console.ReadLine().Split(',');
            var data = new int[strArr.Length];
            for (int i = 0; i < strArr.Length;i++){
                data[i] = int.Parse(strArr[i]);
            }
            GetMinMax(data, out int minVal, out int maxVal);
            Console.WriteLine($"最小値{minVal},最大値{maxVal}");
        }
        public static void GetMinMax(int[] arr,out int min,out int max){
            min = arr[0];
            max = arr[0];
            foreach(var n in arr){
                if(n<min){
                    min = n;
                }
                if(n>max){
                    max = n;
                }
            }
        }
    

    }
}