2009-10-20 13 views
6

Ich brauche ein Feld, das von wo immer ich will zugewiesen werden kann, aber es sollte möglich sein, es nur einmal zuzuweisen (damit nachfolgende Zuweisungen ignoriert werden sollten). Wie kann ich das machen?Ist es möglich, Felder zu haben, die nur einmal zuweisbar sind?

+0

Wenn Sie ihm zuweisen können, wo immer Sie wollen, ist es kaum "schreibgeschützt", oder? Was willst du eigentlich? – AakashM

+2

Das ist wahrscheinlich eine der merkwürdigsten Anforderungen, die ich seit langem gesehen habe. Warum benötigen Sie ein schreibgeschütztes Feld, das nicht schreibgeschützt ist? –

+0

Ich brauche ein schreibgeschütztes Feld, das nur beim ersten Mal zugewiesen werden kann. Was ich will, ist in C# sehr ähnlich wie ein schreibgeschütztes Feld, aber ich möchte, dass seine erste Zuweisung in einer anderen Stelle als dem Konstruktor möglich ist. Ich möchte es für die Verfolgung von Änderungen von Daten verwenden. –

Antwort

17

Das wäre dann kein Readonly-Feld. Die einzigen Optionen zum Initialisieren realer Readonly-Felder sind Feldinitialisierer und Konstruktor.

Sie könnten jedoch eine Art readonly Funktionalität mit Eigenschaften implementieren. Mach dein Feld zu Eigenschaften. Implementieren Sie eine "freeze instance" -Methode, die ein Flag umlegte, das besagt, dass keine Updates für die schreibgeschützten Teile mehr zulässig sind. Lassen Sie Ihre Setter diese Flagge überprüfen.

Denken Sie daran, dass Sie eine Kompilierzeitüberprüfung für eine Laufzeitprüfung aufgeben. Der Compiler wird Ihnen sagen, wenn Sie versuchen, einen Wert zu einem schreibgeschützten Feld von irgendwo außer der Deklaration/Konstruktor zuweisen. Mit dem folgenden Code erhalten Sie eine Ausnahme (oder Sie könnten das Update ignorieren - beide sind keine optimalen IMO).

BEARBEITEN: Um zu vermeiden, die Prüfung zu wiederholen, können Sie das Readonly-Feature in einer Klasse kapseln.

Überarbeitete Umsetzung wie folgt aussehen könnte:

class ReadOnlyField<T> { 
    public T Value { 
     get { return _Value; } 
     set { 
      if (Frozen) throw new InvalidOperationException(); 
      _Value = value; 
     } 
    } 
    private T _Value; 

    private bool Frozen; 

    public void Freeze() { 
     Frozen = true; 
    } 
} 


class Foo { 
    public readonly ReadOnlyField<int> FakeReadOnly = new ReadOnlyField<int>(); 

    // forward to allow freeze of multiple fields 
    public void Freeze() { 
     FakeReadOnly.Freeze(); 
    } 
} 

Dann tun Sie Ihren Code kann so etwas wie

 var f = new Foo(); 

     f.FakeReadOnly.Value = 42; 

     f.Freeze(); 

     f.FakeReadOnly.Value = 1337; 

Die letzte Anweisung wird eine Ausnahme werfen.

+0

Ich verwende derzeit eine solche "Freeze-Instanz" -Lösung, aber meine Klasse hat so viele Felder und es macht keinen Sinn, 5 Zeilen für jedes Feld hinzuzufügen. Aber was ist mit "Feldinitialisierer"? Ich weiß nicht was es ist. Ist es möglich, dort schreibgeschützten Feldern zuzuordnen? Ist das wie "Eigenschaften"? –

+0

Kein Feldinitialisierer hilft Ihnen hier nicht. Es gibt keine Möglichkeit, das zu tun, was Sie mit einem regulären Readonly-Feld fragen. –

+2

@afsharm - Wenn es sich nicht lohnt, 5 Zeilen für jedes Feld hinzuzufügen, dann brauchen Sie diese Funktionalität natürlich nicht (nicht wirklich sicher, warum Sie das sowieso tun würden). – stevehipwell

0

Oder vielleicht meinst du ein Feld, das jeder lesen kann, aber nur die Klasse selbst kann schreiben? Verwenden Sie in diesem Fall ein privates Feld mit einem öffentlichen Getter und einem privaten Setter.

private TYPE field; 

public TYPE Field 
{ 
    get { return field; } 
    private set { field = value; } 
} 

oder eine automatische Eigenschaft:

public TYPE Field { get; private set; } 
+0

Nein! Ich meine es nicht so! Tatsächlich habe ich ein Objekt, das von NHibernate aus der Datenbank befüllt wird und dann an die Benutzeroberfläche übergeben wird. Der Benutzer kann einige Felder bearbeiten oder nicht, aber ich darf Änderungen in bestimmten Feldern nicht zulassen. Eine der Möglichkeiten, die ich dazu erreichen kann, besteht darin, ein Schattenfeld für jedes der Felder als READ ONLY zu definieren und dann diese Schattenfelder mit den ursprünglichen zu vergleichen und festzustellen, ob Änderungen stattgefunden haben. Bitte beachten Sie, dass diese Felder im Konstruktor nicht ausgefüllt sind. –

+0

Wäre es nicht besser, es so zu machen, dass der Benutzer nur einige von ihnen bearbeiten kann, so dass schreibgeschützte Felder in Etiketten anstelle von Textfeldern angezeigt werden, oder so etwas? Wenn Sie das Eigenschaftenraster verwenden, können Sie das Attribut [ReadOnly] darüber setzen. –

+0

Es ist SOA-Anwendung. Wir haben UI im Web, Winform und Konsole und ich darf das nicht irgendwo außerhalb von SERVICE tun. –

1

die folgenden Versuchen:

class MyClass{ 
private int num1; 

public int Num1 
{ 
    get { return num1; } 

} 


public MyClass() 
{ 
num1=10; 
} 

} 
0

in Java und vielleicht in einer anderen Sprache (bitte korrigieren Sie mich, wenn ich falsch liege), Sie können dies tun, indem Sie eine Variable/ein Feld als STATISCH deklarieren (es kann überall zugegriffen werden, solange es öffentlich ist) und FINAL (der Wert kann während der Laufzeit nicht geändert werden, wenn er einmal zugewiesen wurde). :)