【发布时间】:2010-10-08 04:35:12
【问题描述】:
是否可以在不使用 C# 中的 ref/out 关键字的情况下交换两个变量(即使用 unsafe)?
例如,
swap(ref x,ref y);//It is possbile to by passing the reference
但是,有没有其他方法可以做同样的事情。在交换函数中,您可以使用临时变量。但是,如何在不使用 C# 中的 ref/out 关键字的情况下交换变量?
【问题讨论】:
是否可以在不使用 C# 中的 ref/out 关键字的情况下交换两个变量(即使用 unsafe)?
例如,
swap(ref x,ref y);//It is possbile to by passing the reference
但是,有没有其他方法可以做同样的事情。在交换函数中,您可以使用临时变量。但是,如何在不使用 C# 中的 ref/out 关键字的情况下交换变量?
【问题讨论】:
一个(非常!)使用委托的人为示例:
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);
}
}
虽然上述内容非常愚蠢,但在其他情况下使用委托设置器方法可能很有用;我已经使用该技术来实现属性修改的撤消/重做。
【讨论】:
FunkySwap() 执行了两个虚拟方法调用。 Swapable 解决方案的调用站点要短得多,分配一个新对象,并且只在 Swap() 中进行简单的字段加载/存储:)
不,如果没有使用 传递引用,就不可能影响调用者中的变量*。你可以影响班级成员,但你怎么知道你被要求交换哪些成员?ref 或out
*(您可以影响引用类型的实例,并且更改将对调用者可见,但实例不是“变量”。)
【讨论】:
ref 关键字的情况下创建了一个传递引用参数。这确实符合问题的本质,我只是想知道它是否符合精神。
使用元组
int a = 4, b = 8;
(a, b) = (b, a);
【讨论】:
不是真的,除非您对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;
}
}
并且完全忘记了ints 是按值传递的,而且我无法将实际上从调用者复制到被调用者堆栈的东西的指针。
所以它不起作用
看来,我并没有变得更聪明,而是浪费了一些时间,但无论如何还是想与您分享:)
【讨论】:
您可以传递对象中的值并返回该对象的一个实例,并交换了值:
public struct Swapable
{
public int A;
public int B;
}
public Swapable Swap(Swapable swapable)
{
return new Swapable()
{
A = swapable.B;
B = swapable.A;
};
}
【讨论】:
我尝试过使用 unsafe 并且它有效,请参阅代码
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 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();
}
【讨论】: