É algo ganho ao tornar as dependências explícitas através de listas de argumentos de função ao implementar métodos puros?

5

Essa pergunta é uma continuação da pergunta .

Existe algum benefício em evitar o operador 'this' ao implementar métodos puros? Ou seja, há alguma vantagem em tornar todas as dependências explícitas por meio de listas de argumentos, em vez de permitir dependências implícitas referenciando dados de instância através do operador 'this' dentro dos corpos de métodos puros (isso parece tão funky para mim). Eu tenho exemplos de código de cada caso para ajudar a ilustrar minha pergunta.

O exemplo de código a seguir implementa Narrate () como um método instance no qual sua dependência é referenciada através do operador 'this' dentro do corpo do método. O método Main () fornece como essa classe é usada no código do cliente (anote como a saída é gravada):

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

O exemplo de código a seguir implementa Narrate () como um método estático no qual sua dependência é passada por meio da lista de argumentos do método. O método Main () demonstra como essa classe é usada no código do cliente (anote como a saída é gravada):

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)}");
    }
}
    
por Rock Anthony Johnson 25.10.2016 / 22:50
fonte

1 resposta

0

De acordo com a Microsoft ( link )

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.

Então, de acordo com isso, parece que a resposta é não. Este parágrafo parece implicitamente prová-lo, não diferenciando o acesso interno e externo. Se houvesse uma diferença, teria que ser mencionado aqui.

No entanto, no seu exemplo, eu diria que há um efeito colateral de desempenho indesejado que resulta de como você escolheu apresentar esse problema para nós. Se você limitar a pergunta a apenas perguntar sobre o acesso à propriedade sem referência a como o problema está configurado, eu diria que o parágrafo acima prova uma resposta negativa.

Desde que você incluiu um contexto situacional, eu diria que há uma pequena diferença de desempenho. Não é por causa do acesso à propriedade, mas é devido ao fato de que você está adicionando outra referência ao objeto através do argumento.

    
por 26.10.2016 / 07:46
fonte