DI e ipotetici setter di sola lettura in C #

5

A volte vorrei dichiarare una proprietà come questa:

public string Name { get; readonly set; }

Mi chiedo se qualcuno vede una ragione per cui una tale sintassi non dovrebbe esistere. Credo che poiché è un sottoinsieme di "get; private set;", potrebbe solo rendere il codice più solido.

La mia sensazione è che questi setter sarebbero estremamente amichevoli, ma ovviamente sono più interessato a sentire le tue opinioni che le mie, quindi cosa ne pensi tu ?

Sono a conoscenza dei campi "public readonly", ma quelli non sono interfacciati, quindi non li considero nemmeno. Detto questo, non mi dispiace se li porti nella discussione

Modifica

Mi rendo conto di leggere i commenti che forse la mia idea è un po 'confusa. Lo scopo ultimo di questa nuova sintassi è di avere una sintassi della proprietà automatica che specifica che il campo privato di backup deve essere in sola lettura. Sostanzialmente dichiarando una proprietà usando la mia ipotetica sintassi

public string Name { get; readonly set; }

sarebbe interpretato da C # come:

private readonly string name;
public string Name
{
    get
    {
        return this.name;
    }
}

E la ragione per cui dico che sarebbe DI friendly è che quando ci affidiamo pesantemente all'iniezione di un costruttore, credo che sia una buona pratica dichiarare i nostri campi iniettati come readonly.

    
posta Luis Ferrao 12.10.2012 - 14:42
fonte

3 risposte

7

Il team C # ha considerato che questa sarebbe stata una funzione molto utile, ed è per questo che in C # 6 , l'hanno implementata (solo un po 'diversa dalla tua proposta).

Proprietà automatiche di solo assorbimento

Questo nuovo tipo di proprietà è solo getter, ma può essere impostato sia in linea che nel costruttore. Ciò significa che sono supportati internamente da un campo readonly.

Invece di dichiarare una proprietà come readonly set , non devi semplicemente dichiararla.

Assegnazione in linea

public class Customer
{
    public string First { get; } = "Jane";
    public string Last { get; } = "Doe";
}

Assegnazione del costruttore

public class Customer
{
    public string Name { get; }
    public Customer(string first, string last)
    {
        Name = first + " " + last;
    }
}

Puoi leggere su questa e altre nuove funzionalità di C # 6 in Wiki di Roslyn in GitHub .

    
risposta data 16.09.2015 - 19:50
fonte
4

Come menzionato nei commenti, le proprietà sono solo zucchero sintattico. Quando vengono trasformati in metodi, "readonly" non sarebbe più sintatticamente corretto.

Puoi esporre una variabile privata attraverso una proprietà di sola lettura per l'effetto desiderato:

private readonly string _name;

public string Name {
    get {
        return _name;
    }
}

public MyObject(string injectedName) {
    _name = injectedName;
}

Modifica:

Come immagini che la tua idea avrebbe funzionato (se fosse possibile)? La tua proprietà readonly non funzionerebbe in un elenco di inizializzazione perché il costruttore ha già completato l'esecuzione in quel punto.

    
risposta data 12.10.2012 - 15:07
fonte
3

Penso che il tuo problema sia che assumi automaticamente un getter per ogni proprietà iniettata.

Le proprietà automatiche con i setter privati sono per i tipi in cui hai

public class Person
{
    public string Name { get; private set; }
    public int Age { get; private set; }

    public Person (string name, int age)
    {
        Name = name;
        Age = age;
    }
}

e pochissima logica. Ciò significa che non importa se è possibile, tecnicamente parlando, impostare le proprietà automatiche al di fuori del costruttore. Probabilmente non lo farai. E, per quanto riguarda una classe esterna, sei ancora immutabile.

Ma non usi DI per generare oggetti come questo.

Si utilizza DI per iniettare servizi a cui si applica la logica, in questo modo:

public Foo : IFoo
{
    private IBar _bar;
    private IGrommit _grommit;

    public Foo(IBar bar, IGrommit grommit)
    {
        _bar = bar;
        _grommit = grommit;
    }

    public string GrommitMyBarForAName()
    {
        return _grommit.DoStuff(bar).Name;
    }
}

In questi casi, non devi aggiungere automaticamente un accessor per _bar, solo perché è possibile. Non vuoi autorizzare l'accesso ad esso, nemmeno in sola lettura.

Ci saranno casi in cui ti senti necessario ma, in questi casi, dovresti prima riconsiderare il tuo design. Probabilmente è sbagliato.

Se sei assolutamente sicuro di ciò che dovresti, allora aggiungi un accessorio standard, ma questa non dovrebbe essere una situazione abbastanza comune da farti notare che dovrebbe esserci una sintassi per permetterti di avere una proprietà automatica per questo.

    
risposta data 12.10.2012 - 16:30
fonte

Leggi altre domande sui tag