Swap two variables without using ref/out in C#
Is it possible to swap two variables without using ref/out keyword in C#(开发者_StackOverflowi.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 (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.
No, it's not possible to affect variables* in the caller without the use of pass-by-reference. You could affect class members, but how would you know which ones you were being asked to swap?ref
or out
*(You can affect instances of reference types and the changes will be visible to the caller, but instances are not "variables".)
With tuples
int a = 4, b = 8;
(a, b) = (b, 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.
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 int
s 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 :)
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;
};
}
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();
}
}
}
}
here i am passing object as arguments
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();
}
精彩评论