Qualcosa è ottenuto rendendo esplicite le dipendenze tramite gli elenchi di argomenti della funzione quando si implementano metodi puri?

5

Questa domanda è successiva alla domanda .

C'è qualche vantaggio nell'evitare l'operatore "this" quando si implementano metodi puri? Cioè, ci sono dei vantaggi nel rendere esplicite tutte le dipendenze tramite gli elenchi di argomenti, invece di consentire le dipendenze implicite facendo riferimento ai dati dell'istanza tramite l'operatore 'this' all'interno dei corpi di metodi puri (farlo sembra così strano per me). Ho esempi di codice di ogni caso per aiutare a illustrare la mia domanda.

Il seguente esempio di codice implementa Narrate () come metodo istanza in cui la dipendenza viene referenziata tramite l'operatore "this" all'interno del corpo del metodo. Il metodo Main () fornisce il modo in cui questa classe viene utilizzata all'interno del codice client (prendere nota di come l'output è scritto):

public sealed class Version01_MutableLocation
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Version01_MutableLocation North { get; set; }
    public Version01_MutableLocation South { get; set; }
    public Version01_MutableLocation East { get; set; }
    public Version01_MutableLocation West { get; set; }

    /// <summary>
    /// This instance method is a pure function, but it's dependency - the class instance - is referenced via the 'this' operator
    /// </summary>
    public string Narrate()
    {
        string narration = string.Empty;

        { // This block constructs the string that is the description
          // of the location that is displayed onscreen to the game player.
            string northExit =
                null != this.North ? " North" : string.Empty;

            string southExit =
                null != this.South ? " South" : string.Empty;

            string eastExit =
                null != this.East ? " East" : string.Empty;

            string westExit =
                null != this.West ? " West" : string.Empty;

            string allExits =
                string.Empty != string.Concat(northExit, southExit, eastExit, westExit)
                ? $"{Environment.NewLine}Exits:{northExit}{southExit}{eastExit}{westExit}"
                : string.Empty;

            string separator = new string('-', this.Name.Length);

            narration =
                $"{this.Name}{Environment.NewLine}" +
                $"{separator}{Environment.NewLine}" +
                $"{this.Description}{Environment.NewLine}" +
                $"{separator}" +
                $"{allExits}";
        }

        return narration;
    }

    public static void Main(string[] args)
    {
        var kitchen = new Version01_MutableLocation();
        kitchen.Name = "Kitchen";
        kitchen.Description = "You are in a messy kitchen.";

        var library = new Version01_MutableLocation();
        kitchen.Name = "Library";
        kitchen.Description = "You are in the library.";

        var office = new Version01_MutableLocation();
        office.Name = "Office";
        office.Description = "You are in the office. There's a computer on the desk.";

        kitchen.North = library;
        library.South = kitchen;
        library.North = office;
        office.South = library;

        Console.WriteLine($"{kitchen.Narrate()}");
        Console.WriteLine($"{library.Narrate()}");
        Console.WriteLine($"{office.Narrate()}");
    }
}

Il seguente esempio di codice implementa Narrate () come metodo static in cui la dipendenza viene passata tramite l'elenco degli argomenti del metodo. Il metodo Main () dimostra come questa classe viene utilizzata all'interno del codice client (prendere nota di come l'output è scritto):

public sealed class Version02_MutableLocation
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Version02_MutableLocation North { get; set; }
    public Version02_MutableLocation South { get; set; }
    public Version02_MutableLocation East { get; set; }
    public Version02_MutableLocation West { get; set; }

    /// <summary>
    /// This static method is a pure function, and all of its dependencies are passed in the function's argument list.
    /// </summary>
    public static string Narrate(Version02_MutableLocation location)
    {
        string narration = string.Empty;

        { // This block constructs the string that is the description
          // of the location that is displayed onscreen to the game player.
            string northExit =
                null != location.North ? " North" : string.Empty;

            string southExit =
                null != location.South ? " South" : string.Empty;

            string eastExit = 
                null != location.East ? " East" : string.Empty;

            string westExit = 
                null != location.West ? " West" : string.Empty;

            string allExits =
                string.Empty != string.Concat(northExit, southExit, eastExit, westExit)
                ? $"{Environment.NewLine}Exits:{northExit}{southExit}{eastExit}{westExit}"
                : string.Empty;

            string separator = new string('-', location.Name.Length);

            narration =
                $"{location.Name}{Environment.NewLine}" +
                $"{separator}{Environment.NewLine}" +
                $"{location.Description}{Environment.NewLine}" +
                $"{separator}" +
                $"{allExits}";
        }

        return narration;
    }

    public static void Main(string[] args)
    {
        var kitchen = new Version02_MutableLocation();
        kitchen.Name = "Kitchen";
        kitchen.Description = "You are in a messy kitchen.";

        var library = new Version02_MutableLocation();
        kitchen.Name = "Library";
        kitchen.Description = "You are in the library.";

        var office = new Version02_MutableLocation();
        office.Name = "Office";
        office.Description = "You are in the office. There's a computer on the desk.";

        kitchen.North = library;
        library.South = kitchen;
        library.North = office;
        office.South = library;

        Console.WriteLine($"{Version02_MutableLocation.Narrate(kitchen)}");
        Console.WriteLine($"{Version02_MutableLocation.Narrate(library)}");
        Console.WriteLine($"{Version02_MutableLocation.Narrate(office)}");
    }
}
    
posta Rock Anthony Johnson 25.10.2016 - 22:50
fonte

1 risposta

0

Secondo Microsoft ( collegamento )

The body of the get accessor resembles that of a method. It must return a value of the property type. The execution of the get accessor is equivalent to reading the value of the field. For example, when you are returning the private variable from the get accessor and optimizations are enabled, the call to the get accessor method is inlined by the compiler so there is no method-call overhead. However, a virtual get accessor method cannot be inlined because the compiler does not know at compile-time which method may actually be called at run time.

Quindi, secondo questo, sembra che la risposta sia no. Questo paragrafo sembra implicitamente dimostrarlo non differenziando l'accesso interno ed esterno. Se ci fosse una differenza, dovrebbe essere menzionata qui.

Tuttavia, nel tuo esempio, direi che c'è un indesiderato effetto collaterale sulle prestazioni che deriva dal modo in cui hai scelto di presentarci questo problema. Se si limita la domanda a chiedere semplicemente l'accesso alla proprietà senza riferimento a come viene impostato il problema, direi che il paragrafo precedente dimostra una risposta "no".

Dato che hai incluso un contesto situazionale, direi che c'è una leggera differenza di prestazioni. Non è a causa dell'accesso alla proprietà, ma piuttosto è dovuto al fatto che stai aggiungendo un altro riferimento all'oggetto attraverso l'argomento.

    
risposta data 26.10.2016 - 07:46
fonte

Leggi altre domande sui tag