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

C# 在C中不使用ref/out交换两个变量,c#,keyword,swap,C#,Keyword,Swap,在Ci.e中不使用ref/out关键字就可以交换两个变量吗。使用不安全的 例如 swap(ref x,ref y);//It is possbile to by passing the reference 但是,有没有其他方法可以做同样的事情呢。在swap函数中,可以使用temp变量。但是,如何在不使用C中的ref/out关键字的情况下交换变量?您可以在对象中传递值,然后返回该对象的一个实例以及交换的值: public struct Swapable { public

在Ci.e中不使用ref/out关键字就可以交换两个变量吗。使用不安全的

例如

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

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

您可以在对象中传递值,然后返回该对象的一个实例以及交换的值:

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

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

不,如果不使用ref或out pass by reference,就不可能影响调用者中的变量*。你可以影响班上的成员,但你怎么知道你被要求交换哪些成员呢


*您可以影响引用类型的实例,并且调用方可以看到这些更改,但实例不是变量。

我尝试过使用不安全的方法,它可以工作,请参阅代码

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();

        }
    }
}

}一个非常好的选择!使用委托的人为示例:

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);
    }
}

尽管上述方法非常愚蠢,但在其他情况下使用委托设置器方法可能会很有用;我使用了这种技术来实现属性修改的撤销/重做。

不是真的,除非您对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;
    }
}
但实际上唯一的实际区别是引用可以避免的所有指针陷阱,以及它必须是不安全的事实。它基本上也在做同样的事情。

我试过这个

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是通过值传递的,我无法获取从调用方复制到被调用方堆栈的东西的指针

所以它不起作用

看来,我并没有变得更聪明,只是浪费了一些时间,但我还是想和你们分享一下:

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

带元组

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

他在问是否可以使用不安全的代码块,因为不安全的代码块允许使用指针,所以说可以在没有ref或ref的情况下完成是不正确的out@Rune:您只是通过ref参数传递,而不使用ref关键字。这确实符合问题的字面意思,我只是想知道它是否符合精神。这很好,很可怕,但作为一个回答,这很好,因为我们不能传递没有ref的变量,或者用指针或对象包含伪造ref,你只能传递函数!很好的横向思维。虽然看起来一点都不相似,但这是迈克尔·希明斯的答案的翻版。@Ben Voigt:怎么会这样?他的分配一个新的结构,我的使用委托并更改原始引用。啊,你说得对,返回一个结构不是那么相似。但是,闭包的使用与将要交换的值放入类实例,调用函数交换成员,然后从类实例读回成员完全相同,因为MSIL代码实际上就是这样做的。@Ben Voigt:,在生成的MSIL代码中有很大的不同-但是你是对的,有相当多的开销是从C代码中看不到的。在每个调用站点,我们构造了两个Action对象,FunkySwap执行两个虚拟方法调用。可交换解决方案具有更短的调用站点,分配单个新对象,并且仅在交换中执行简单的字段加载/存储:
int a = 4, b = 8;
(a, b) = (b, a);