C# 在C中不使用ref/out交换两个变量
在Ci.e中不使用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
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);