简体   繁体   English

如何在C#中通过引用传递

[英]How to pass by reference in C#

I am writing a Quick sorting class mimicking the code given in "Algorithms 4" by Sedgewick. 我正在编写一个快速排序类,它模仿Sedgewick在“算法4”中给出的代码。 The original code is written in Java. 原始代码是用Java编写的。 I translated in C# the core part but it doesn't seem to work. 我用C#翻译了核心部分,但似乎没有用。 It seems like the problem is in the line a = a.OrderBy(x => r.Next()).ToArray() but I don't know how to correct it. 看来问题出在a = a.OrderBy(x => r.Next()).ToArray()但我不知道如何纠正它。

I tried to add ref in the Sort s and Partition method signatures but once I call the function Sort(ref a) in Main , the compliler complaints that cannot converte ref System.String[] to ref System.IComparable[] . 我尝试添加refSort S和Partition方法签名,但一旦我调用函数Sort(ref a)Main的compliler抱怨cannot converte ref System.String[] to ref System.IComparable[] I also tried to make the first Sort return an IComparable[] , the sorted array. 我还尝试使第一个Sort返回一个IComparable[] (排序后的数组)。 However, when I call it in the Main like this string[] nums = (string[]) Sort(nums) , it throws a runtime error says Unable to cast object of type 'System.IComparable[]' to type 'System.String[]'. 但是,当我像这样的string[] nums = (string[]) Sort(nums)Main调用它时,它抛出运行时错误,提示Unable to cast object of type 'System.IComparable[]' to type 'System.String[]'.

public class Quick
{
    public static void Sort(IComparable[] a)
    {
        Random r = new Random();
        a = a.OrderBy(x => r.Next()).ToArray();
        Sort(a, 0, a.Length - 1);
    }

    private static void Sort(IComparable[] a, int lo, int hi)
    {
        if (lo >= hi) return;
        int p = Partition(a, lo, hi);
        Sort(a, lo, p - 1);
        Sort(a, p + 1, hi);
    }

    private static int Partition(IComparable[] a, int lo, int hi)
    {
        int i = lo, j = hi;
        IComparable p = a[lo];
        while (true)
        {
            while (Less(a[++i], p))
            {
                if (i == hi)
                    break;
            }

            while (Less(p, a[--j]))
            {
                if (j == lo)
                    break;
            }

            if (i >= j) break;

            Exch(a, i, j);
        }
        Exch(a, lo, j);
        return j;
    }

    private static void Exch(IComparable[] a, int lo, int hi)
    {
        IComparable tmp = a[lo];
        a[lo] = a[hi];
        a[hi] = tmp;
    }

    private static bool Less(IComparable a, IComparable b)
    {
        return a.CompareTo(b) < 0;
    }


    public static void Main(string[] args)
    {
        string[] nums = File.ReadAllLines(args[0]);
        for (int i = 0; i < nums.Length; i++)
        {
            Console.WriteLine(nums[i]);
        }
        Sort(nums);
        Console.WriteLine("After sorting:");
        for (int i = 0; i < nums.Length; i++)
        {
            Console.WriteLine(nums[i]);
        }
        Console.ReadKey();
    }
}

The seconde WriteLine should print out the sorted array but it doesn't. Seconde WriteLine应该打印出排序后的数组,但不是。

The problem here is not pass by reference, it is this line, as you have identified: 您所确定的问题不是通过引用传递的,而是此行:

a = a.OrderBy(x => r.Next()).ToArray();

You are giving a a new value, which is different from just modifying the contents of a . 你给a新的价值,这是从刚刚修改的内容不同的a Since the Sort method sorts the array in place, you should not create a new array, and the array doesn't have to be shuffled before you sort it. 由于Sort方法对数组进行了适当的Sort ,因此您不应该创建新的数组,并且在对数组进行排序之前不必对其进行混洗。

So deleting these two lines should make your code work: 因此,删除这两行应该可以使您的代码正常工作:

Random r = new Random();
a = a.OrderBy(x => r.Next()).ToArray();

You seem to encounter some problems when you try to return the array from Sort . 当您尝试从Sort返回数组时,您似乎遇到了一些问题。 You can fix this by making all your methods generic, with a generic parameter T constrained to IComparable<T> : 您可以通过使所有方法通用,并使用通用参数T限制为IComparable<T>来解决此问题:

public static T[] Sort<T>(T[] a) where T: IComparable<T>
{
    Random r = new Random();
    a = a.OrderBy(x => r.Next()).ToArray();
    Sort(a, 0, a.Length - 1);
    return a;
}

private static void Sort<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
    if (lo >= hi) return;
    int p = Partition(a, lo, hi);
    Sort(a, lo, p - 1);
    Sort(a, p + 1, hi);
}

private static int Partition<T>(T[] a, int lo, int hi) where T: IComparable<T>
{
    int i = lo, j = hi;
    T p = a[lo];
    while (true)
    {
        while (Less(a[++i], p))
        {
            if (i == hi)
                break;
        }

        while (Less(p, a[--j]))
        {
            if (j == lo)
                break;
        }

        if (i >= j) break;

        Exch(a, i, j);
    }
    Exch(a, lo, j);
    return j;
}

private static void Exch<T>(T[] a, int lo, int hi)
{
    T tmp = a[lo];
    a[lo] = a[hi];
    a[hi] = tmp;
}

private static bool Less<T>(T a, T b) where T: IComparable<T>
{
    return a.CompareTo(b) < 0;
}

You need to return the sorted array since, like you said, it's passed by value and not by reference. 您需要返回已排序的数组,因为就像您所说的那样,它是按值而不是引用传递的。 Add return type instead of void to the Sort method and return a; 将返回类型而不是void添加到Sort方法中,并返回a;

And change 并改变

Sort(nums); 排序(数字);

to

nums=Sort(nums); nums = Sort(nums);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM