在C#中不使用ref / out交换两个变量

时间:2010-10-08 04:35:12

标签: c# keyword swap

是否可以在C#中不使用ref / out关键字交换两个变量(即使用unsafe)?

为前,

        swap(ref x,ref y);//It is possbile to by passing the reference

但是,还有其他方法可以做同样的事情。在交换函数中,您可以使用临时变量。但是,如何在不使用C#中的ref / out关键字的情况下交换变量?

8 个答案:

答案 0 :(得分:4)

使用代表的一个(非常!)人为的例子:

class Program
{
    static void FunkySwap<T>(T a, T b, Action<T> setA, Action<T> setB)
    {
        T tempA = a;
        setA(b);
        setB(tempA);
    }
    static void Main(string[] args)
    {
        string s1 = "big";
        string s2 = "apples";
        Console.WriteLine("BEFORE, s1: {0}, s2: {1}", s1, s2);
        FunkySwap(s1, s2, a => s1 = a, b => s2 = b);
        Console.WriteLine("AFTER,  s1: {0}, s2: {1}", s1, s2);
    }
}

虽然上面的内容非常愚蠢,但使用委托setter方法在其他情况下非常有用;我已经使用该技术来实现属性修改的撤销/重做。

答案 1 :(得分:2)

不,如果没有使用refout 传递引用,就不可能影响调用者中的变量*。你可能会影响班级成员,但是你怎么知道你被要求交换哪些?

*(您可以影响引用类型的实例,并且调用者可以看到更改,但实例不是“变量”。)

答案 2 :(得分:1)

不是真的,除非您对ref的唯一问题是不喜欢这个词本身。

您可以通过指针交换,例如:

public unsafe void Swap(int* x, int* y)
{
    unsafe
    {//lets not use a temp, just to be different!
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

但实际上唯一的实际区别是引用的所有指针陷阱都会使您免于死亡,以及它必须是不安全的。它基本上做同样的事情。

答案 3 :(得分:1)

我试过这个

class Program
{
    static void Main(string[] args)
    {
        int x = 3;
        int y = 6;
        Console.Write(string.Format("before swap x={0} y={1}", x, y));
        Swap(x, y);
        Console.Write(string.Format("after swap x={0} y={1}", x, y));
        Console.ReadKey();
    }

    static public unsafe void Swap(int a, int b)
    {
        int* ptrToA = &a;
        int* ptrToB = &b;
        int c = a;
        *ptrToB = c;
        *ptrToB = *ptrToA;
    }
}

完全忘记了int是按值传递的,并且我无法从调用者到被调用者堆栈中获取实际COPIED的指针。

所以它不起作用

所以看起来,我不是更聪明,而是浪费了一些时间但是想与你分享:)

答案 4 :(得分:0)

您可以传递对象中的值,并返回该对象的实例,其值为swapped:

public struct Swapable
{
    public int A;
    public int B;
}

public Swapable Swap(Swapable swapable)
{
    return new Swapable()
    {
        A = swapable.B;
        B = swapable.A;
    };
}

答案 5 :(得分:0)

我尝试过使用不安全的方法并且有效,请参阅代码

namespace ConsoleApplication2
{
class myclass
{
    public unsafe void swap(int *x, int *y)
    {
        unsafe
        {
            int temp = 0;
            temp = *x;
            *x = *y;
            *y = temp;
            Console.WriteLine("Using Swap1");
            Console.WriteLine("x:"+*x);
            Console.WriteLine("y:" + *y);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        unsafe
        {
            int x = 10;
            int y = 20;
            int* t1 = &x;
            int* t2 = &y;
            myclass m1 = new myclass();
            m1.swap(t1,t2);
            Console.WriteLine("Main");
            Console.WriteLine("x: " + x);
            Console.WriteLine("y: " + y);
            Console.ReadLine();

        }
    }
}

}

答案 6 :(得分:0)

  

这里我将对象作为参数传递

class person1
            {
                public int x, y;
                public person1(int x,int y)
                    {
                    this.x = x;
                    this.y = y;

                    }
                public void changes(person1 p1)
                {
                   // int t;
                    this.x = x + y;  //x=30 x=10,y=20
                    this.y = x - y;  //y=30-20=10
                    this.x = x - y; //x=30-10=20
                }
    }
     static void Main(string[] args)
       {
             person1 p1 = new person1(10,20);
             p1.changes(p1);
             Console.WriteLine("swapp hoge kya ?x={0} and y={1}", p1.x, p1.y);
             Console.ReadKey();
      }

答案 7 :(得分:0)

使用元组

int a = 4, b = 8;
(a, b) = (b, a);