2010-10-08 6 views
1

Est-il possible d'échanger deux variables sans utiliser le mot-clé ref/out en C# (c'est-à-dire en utilisant unsafe)?Échange de deux variables sans utiliser ref/out en C#

Ex,

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

Mais, est-il une autre façon de faire la même chose. Dans la fonction d'échange, vous pouvez utiliser une variable temp. Mais, Comment échanger les variables sans utiliser les mots-clés ref/out en C#?

Répondre

4

A (! très) par exemple en utilisant les délégués: contrived

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

Alors que ce qui précède est assez bête, l'utilisation d'une méthode de définition de délégué peut être utile dans d'autres situations; J'ai utilisé la technique pour implémenter annuler/refaire des modifications de propriété.

+0

C'est assez sympa (bon, c'est assez horrible, mais c'est sympa comme réponse), puisque nous ne pouvons pas passer les variables sans ref ou feindre ref avec des pointeurs ou confinement d'objet, on passe dans la fonction à la place! Bonne pensée latérale. –

+0

+1 for funkyness – sloth

+0

Même s'il ne ressemble en rien, c'est une copie de la réponse de Michael Shimmins. –

0

Vous pouvez transmettre les valeurs dans un objet et renvoie une instance de cet objet avec les valeurs permutés:

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

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

Non, il est impossible d'affecter les variables * dans l'appelant sans l'utilisation de ref ou out référence par renvoi. Vous pourriez toucher les membres du groupe, mais comment sauriez-vous lesquels vous étiez invités à échanger?

* (Vous pouvez affecter des instances de types de référence et les changements seront visibles à l'appelant, mais les cas ne sont pas « variables ».)

+2

Eh bien il demande si dangereux peut-il être utilisé et que les blocs de code dangereux permettent des pointeurs, il est incorrect de indique qu'il peut être fait sans ref ou out –

+0

@Rune: Vous faites juste un paramètre pass-by-ref sans utiliser le mot-clé 'ref'. Cela répond à la lettre de la question, je dois juste me demander si cela correspond à l'esprit. –

0

J'ai essayé d'utiliser dangereux et il fonctionne, voir le 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(); 

     } 
    } 
} 

}

0

Pas vraiment, sauf si votre seul problème avec ref est une aversion pour le mot lui-même.

Vous pouvez échanger par le biais des pointeurs, comme:

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

Mais vraiment la seule différence est pratique tous les pièges de pointeur que les références de vous faire économiser, ainsi que le fait qu'il doit être dangereux. C'est fondamentalement faire la même chose.

1

J'ai essayé

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

complètement oublié que int s sont passés par valeur, et il n'y a aucun moyen que je peux prendre un pointeur de quelque chose qui est en fait COPIER de l'appelant à la pile de callee.

il ne fonctionne pas

Il semble donc, au lieu d'être plus intelligent, je viens de perdre un peu de temps mais que vous voulez partager avec vous de toute façon :)

0

ici je passe objet comme 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(); 
     } 
Questions connexes