2010-07-19 3 views
6

In C++ Ich kann dies tun:Kann ich eine Referenz in einer C# -Funktion wie C++ verwenden?

int flag=0,int1=0,int2=1; 
int &iRef = (flag==0?int1:int2); 
iRef +=1; 

mit dem Effekt, dass erhöht wird INT1.

Ich muss einige ältere C# -Code ändern und es wäre wirklich hilfreich, wenn ich etwas ähnliches tun könnte, aber ich denke ... vielleicht nicht. Irgendjemand?

+0

Siehe auch: http://stackoverflow.com/questions/4542536/is-it-possible-to-return-a-reference-to-a-variable-in-c/4542706#4542706 – Betamoo

Antwort

5

Sie können es tun - oder zumindest etwas sehr ähnlich zu dem, was Sie wollen - aber es ist wahrscheinlich am besten, einen anderen Ansatz zu finden. Beispielsweise können Sie die Ganzzahlen innerhalb eines einfachen Referenztyps umbrechen.

Wenn Sie immer noch, es tun möchten, finden Sie in der Ref<T> Klasse geschrieben von Eric Lippert here:

sealed class Ref<T> 
{ 
    private readonly Func<T> getter; 
    private readonly Action<T> setter; 
    public Ref(Func<T> getter, Action<T> setter) 
    { 
     this.getter = getter; 
     this.setter = setter; 
    } 
    public T Value { get { return getter(); } set { setter(value); } } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     int flag=0,int1=0,int2=1; 

     Ref<int> iRef = (flag == 0 ? 
      new Ref<int>(() => int1, z => { int1 = z; }) : 
      new Ref<int>(() => int2, z => { int2 = z; })); 

     iRef.Value += 1; 

     Console.WriteLine(int1); 
    } 
} 

Ausgang:

1 
+0

Danke für den Tipp. Ich werde das überprüfen. – Gio

1

Fraid nicht. Man könnte es tun mit unsafe Code und Zeiger wie folgt:

int flag=0,int1=0,int2=1; 
    unsafe 
    { 
     int *iRef = (flag==0? &int1:&int2); 
     *iRef +=1; 
    } 

(nicht sagen, das ist eine gute Idee oder etwas :))

2

Wenn alles, was Sie benötigen einen Werttyp innerhalb einer Funktion zu ändern ist, dann übergeben Sie den Parameter mit dem Schlüsselwort ref.

int i = 0;

void increment(ref int integer) 
{ 
    integer++; 
} 

increment(ref i); 

+0

Do not möchte eine Funktion in Unterfunktionen zerlegen, nur um eine Referenz zu verwenden. Danke trotzdem. – Gio

+0

@Gio: Ich habe noch einen Fall zu sehen, in dem eine passend benannte Funktion die Lesbarkeit nicht verbessert. Wenn ich entweder den Typ 'Ref ' von Mark ('clevere Idee,' + 1' von mir) entziffern will und eine Funktion, die ein Argument mit 'ref' nimmt, würde ich sicherlich eine Funktion bevorzugen. – sbi

1

Es gibt keine direkte equivelent in C#. Es gibt ein paar Optionen -

Sie können unsafe code and pointers as suggested by dkackman verwenden.

Eine andere Alternative ist die Verwendung eines Referenztyps (Klasse), der den Wert enthält. Für exmaple:

// Using something like 
public class Wrapped<T> { 
    public Wrapped(T initial) { 
     this.Value = initial; 
    } 
    public T Value { get; set; } 
} 

// You can do: 
bool flag=false; 
var int1 = new Wrapped<int>(0); 
var int2 = new Wrapped<int>(1); 

Wrapped<int> iRef = flag ? int2 : int1; 

iRef.Value = iRef.Value + 1; 

Da Sie mit Referenzen zu einer Klasse arbeiten, die Zuordnung zu iRef kopiert die Referenz, und die oben genannten Arbeiten ...

8

UPDATE: Das unten diskutierte Feature schließlich in wurde hinzugefügt C# 7.


Die Funktion, die Sie wollen - verwaltet lokale Variable Aliase machen nicht in C# unterstützt. Sie können es mit formalen Parametern tun - Sie können einen formalen Parameter, der ein Alias ​​einer Variablen ist - aber Sie können keine lokale machen, die ein Alias ​​einer Variablen ist.

Allerdings gibt es keine technische Schwierigkeit, uns davon abzuhalten; Das CLR-Typsystem unterstützt "ref local variables". (Es unterstützt auch Ref-Return-Typen, unterstützt aber Ref-Felder nicht.)

Vor ein paar Jahren schrieb ich tatsächlich eine Prototyp-Version von C#, Ref-Locals und Ref-Return-Typen unterstützt, und es hat sehr gut funktioniert, so dass wir empirisch sind Beweise, dass wir das erfolgreich machen können. Es ist jedoch sehr unwahrscheinlich, dass diese Funktion in naher Zukunft zu C# hinzugefügt wird.Details siehe http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/.

Ich bemerke, dass wenn ich Sie wäre, würde ich dies in keiner Sprache vermeiden. Das Schreiben von Programmen, in denen zwei Variablen den gleichen Speicher teilen, macht Code, der schwer zu lesen, schwer zu verstehen, schwer zu modifizieren und schwer zu pflegen ist.

Siehe auch die damit verbundene Frage: Why doesn't C# support the return of references?

+0

Ich habe dieses Idiom für Kommandozeilen-Tools verwendet, die entweder aus einer Datei lesen, die als Parameter oder stdin übergeben wurde: 'std :: istream & is = blah()? ifs: std :: cin'. Ich würde eine Funktion entweder mit "ifs" oder "std :: cin" aufrufen, aber andere scheinen zusätzlichen Funktionsaufrufen abgeneigt zu sein. – sbi

+0

@sbi: Aber in C# ist ein Stream schon ein Referenztyp, also gibt es in C# kein Problem: Stream s = f? s1: s2;, keine Sorge. Dies wird erst interessant, wenn die Variable wie in Gio's Beispiel vom * Werttyp * ist. Es gibt keine Möglichkeit, zwei * value type * locals Aliasnamen für einander in C# zu erstellen, ohne formale Parameter zu verwenden. –

+1

Ich habe das verstanden. Ich antwortete nur auf Ihre Aussage "Programme zu schreiben, in denen zwei Variablen den gleichen Speicher teilen, macht Code schwer lesbar, schwer zu verstehen, schwer zu modifizieren und schwer zu warten." Es ist nicht immer so. – sbi

1

Sie könnten eine Action delegate wie folgt verwenden:

int flag = 0, int1 = 0, int2 = 0; 
Action increment = flag == 0 ? (Action) (() => ++int1) :() => ++int2; 
increment(); 
2

Ja Sie, dass mit C# 7.0 tun können. Es unterstützt die Rückgabe von Referenzen und das Speichern von Referenzen. Siehe meine Antwort here.

Verwandte Themen