tags:

views:

146

answers:

6

Is it possible to swap two variables without using ref/out keyword in C#(i.e. by using unsafe)?

for ex,

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

But, Is there any other way of doing the same thing. In the swap function you can use a temp variable. But, How to swap the variables without using ref/out keywords in C#?

A: 

You could pass the values in an object and return an instance of that object with the values swapped:

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

public Swapable Swap(Swapable swapable)
{
    return new Swapable()
    {
        A = swapable.B;
        B = swapable.A;
    };
}
Michael Shimmins
+2  A: 

No, it's not possible to affect variables* in the caller without the use of ref or out pass-by-reference. You could affect class members, but how would you know which ones you were being asked to swap?

*(You can affect instances of reference types and the changes will be visible to the caller, but instances are not "variables".)

Ben Voigt
Well he's asking if unsafe Can be used and since unsafe code blocks allow pointers it's incorrect to state that it Can be done without ref or out
Rune FS
@Rune: You're just making a pass-by-ref parameter without using the `ref` keyword. That does meet the letter of the question, I just have to wonder if it meets the spirit.
Ben Voigt
A: 

I have tried using unsafe and it works, see the code

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

        }
    }
}

}

wiz kid
+2  A: 

A (very!) contrived example using delegates:

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

While the above is pretty silly, using a delegate setter method can be useful in other situations; I've used the technique for implementing undo/redo of property modifications.

snemarch
That's quite nice (well, it's quite horrible, but it's nice as an answer), since we can't pass the variables without ref or faking ref with pointers or object-containment, you pass in the function instead! Good lateral thinking.
Jon Hanna
+1 for funkyness
dkson
Even though it looks nothing alike, this is a duplicate of Michael Shimmins's answer.
Ben Voigt
@Ben Voigt: how so? His allocates a new struct, mine uses delegates and changes the original references.
snemarch
Ah, you're right, returning a struct is not so similar. However your use of closures is exactly the same as putting the values to be swapped into a class instance, calling a function to swap the members, and then reading them back from the class instance, because that's what the MSIL code actually does.
Ben Voigt
@Ben Voigt: well, there's a big difference in the generated MSIL code - but you're right that there's a fair amount of overhead which isn't visible from the C# code. At each *call site* we get two Action objects constructed, and `FunkySwap()` performs two virtual method calls. The `Swapable` solution has a much shorter call site, allocates a single new object, and only does simple field load/store in `Swap()` :)
snemarch
A: 

Not really, unless your only issue with ref is a dislike of the word itself.

You can swap through pointers, like:

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

But really the only practical difference is all the pointer pitfalls that references save you from, along with the fact that it has to be unsafe. It's basically doing the same thing.

Jon Hanna
+1  A: 

I tried this

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

And completely forgot that ints are passed by value, and there is no way I can take a pointer of something that is actually COPIED from the caller to the callee stack.

so it doesn't work

So it seems, instead of being smarter, I just wasted some time but want to share that with you anyway :)

Daniel Mošmondor