Share via


Escolhendo entre propriedades e métodos

Em geral, os métodos representam ações e propriedades representam os dados. Propriedades devem ser usados como campos, significando que propriedades não devem ser computacionais complexos ou produzir efeitos colaterais. Ao que não violem as diretrizes a seguir, considere usar uma propriedade, em vez de um método, porque os desenvolvedores experientes menos encontrar propriedades mais fáceis de usar.

Considere o uso de uma propriedade se o membro representa um atributo do tipo de lógico.

Por exemplo, BorderStyle é uma propriedade como o estilo da borda é um atributo de um ListView.

Use uma propriedade, em vez de um método, se o valor da propriedade é armazenado na memória do processo e a propriedade seria apenas fornecer acesso ao valor.

O exemplo de código a seguir ilustra essa diretriz. The EmployeeRecord classe define duas propriedades que fornecem acesso a campos particulares. O exemplo completo é mostrado no participante deste tópico.

Public Class EmployeeRecord

    Private employeeIdValue as Integer
    Private departmentValue as Integer

    Public Sub New()
    End Sub

    Public Sub New (id as Integer, departmentId as Integer)
        EmployeeId = id
        Department = departmentId
    End Sub

    Public Property Department as Integer
        Get 
            Return departmentValue
        End Get
        Set 
            departmentValue = value
        End Set
    End Property

    Public Property EmployeeId as Integer
        Get 
            Return employeeIdValue
        End Get
        Set 
            employeeIdValue = value
        End Set
    End Property
    Public Function Clone() as EmployeeRecord
        Return new EmployeeRecord(employeeIdValue, departmentValue)
    End Function
End Class
public class EmployeeRecord
{
    private int employeeId;
    private int department;
    public EmployeeRecord()
    {
    }
    public  EmployeeRecord (int id, int departmentId)
    {
        EmployeeId = id;
        Department = departmentId;
    }
    public int Department
    {
        get {return department;}
        set {department = value;}
    }
    public int EmployeeId
    {
        get {return employeeId;}
        set {employeeId = value;}
    }
    public EmployeeRecord Clone()
    {
        return new EmployeeRecord(employeeId, department);
    }
}

Use um método, em vez de uma propriedade, nas situações a seguir.

  • A operação é muito mais lento do que seria um conjunto de campos. Se você ainda estiver pretendendo fornecendo uma versão assíncrono de uma operação para evitar o bloqueio do thread, é muito provável que a operação é muito cara ser uma propriedade. Em particular, as operações que acessam a rede ou o sistema de arquivos (diferente de uma vez para inicialização) é mais provável que devem ser métodos, propriedades não.

  • A operação é uma conversão, sistema autônomo a Object.ToString method.

  • A operação retornar um resultado diferente a cada time é chamado, mesmo se os parâmetros não alteram. Por exemplo, a NewGuid método retorna um valor diferente a cada time é chamado.

  • A operação tem um efeito colateral significativo e observável. Observe que preencher um cache interno não é geralmente considerada um efeito colateral observável.

  • A operação retorna uma cópia de um estado interno (isso não inclui cópias de objetos de tipo do valor retornados na pilha).

  • A operação retorna uma matriz.

Use um método em que a operação retorna uma matriz porque para preservar a matriz interna, você teria que retorne uma cópia em profundidade do array, não uma referência para o array utilizando a propriedade. Esse fato, combinado com o fato de que sistema autônomo desenvolvedores usar propriedades sistema autônomo se fossem campos, pode gerar código muito ineficiente. Isso é ilustrado no exemplo de código a seguir, que retorna uma matriz usando uma propriedade. O exemplo completo é mostrado no participante deste tópico.

Public Class EmployeeData

    Dim data as EmployeeRecord()
    Public Sub New(data as EmployeeRecord())
        Me.data = data
    End Sub
    Public ReadOnly Property Employees as EmployeeRecord()
        Get
            Dim newData as EmployeeRecord() = CopyEmployeeRecords()
            Return newData
        End Get
    End Property

    Private Function CopyEmployeeRecords() as EmployeeRecord()
        Dim newData(UBound(data)) as EmployeeRecord
        For i as Integer = 0 To UBound(data)
            newData(i) = data(i).Clone()
        Next i
        Console.WriteLine ("EmployeeData: cloned employee data.")
        Return newData
    End Function
End Class
public class EmployeeData
{
    EmployeeRecord[] data;
    public EmployeeData(EmployeeRecord[] data)
    {
        this.data = data;
    }
    public EmployeeRecord[] Employees
    {
        get 
        {
            EmployeeRecord[] newData = CopyEmployeeRecords();
            return newData;
        }
    }
    EmployeeRecord[] CopyEmployeeRecords()
    {
        EmployeeRecord[] newData = new EmployeeRecord[data.Length];
        for(int i = 0; i< data.Length; i++)
        {
            newData[i] = data[i].Clone();
        }
        Console.WriteLine ("EmployeeData: cloned employee data.");
        return newData;
    }
}

Um desenvolvedor usando este clsistema autônomos sistema autônomo sumes que a propriedade é não mais cara do que o acesso a um campo e grava bsistema autônomoed de código do aplicativo em que sumption sistema autônomo sistema autônomo mostrado no exemplo de código a seguir.

Public Class RecordChecker
    Public Shared Function  FindEmployees( _
         dataSource as EmployeeData, _
         department as Integer) as Collection(Of Integer)

        Dim storage as Collection(Of Integer) = new Collection(Of Integer)()
        Console.WriteLine("Record checker: beginning search.")
        For i as Integer = 0 To UBound(dataSource.Employees)
            If dataSource.Employees(i).Department = department
                Console.WriteLine("Record checker: found match at {0}.", i)
                storage.Add(dataSource.Employees(i).EmployeeId)
                Console.WriteLine("Record checker: stored match at {0}.", i)
            Else 
                Console.WriteLine("Record checker: no match at {0}.", i)
            End If
        Next i
        Return storage
    End Function
End Class
public class RecordChecker
{
    public static Collection<int> FindEmployees(EmployeeData dataSource, 
             int department)
    {
        Collection<int> storage = new Collection<int>();
        Console.WriteLine("Record checker: beginning search.");
        for (int i = 0; i < dataSource.Employees.Length; i++)
        {
            if (dataSource.Employees[i].Department == department)
            {
                Console.WriteLine("Record checker: found match at {0}.", i);
                storage.Add(dataSource.Employees[i].EmployeeId);
                Console.WriteLine("Record checker: stored match at {0}.", i);
            }
            else 
            {
                Console.WriteLine("Record checker: no match at {0}.", i);
            }
        }
        return storage;
    }
}

Observe que o Employees propriedade for acessada em cada iteração do loop e também acessada quando coincidem com os departamentos. Toda vez que a propriedade for acessada, uma cópia da matriz funcionários é criada, usado rapidamente e, em seguida, requer a coleta de lixo. Implementando Employees sistema autônomo um método, você indicar aos desenvolvedores esta ação é mais computacionalmente cara do que acessar um campo. Os desenvolvedores têm maior probabilidade de chamar um método uma vez e armazenar em cache os resultados da telefonar do método para realizar seu processamento.

Exemplo

O exemplo de código a seguir mostra um aplicativo completo pressupõe que uma propriedade de acesso é computacionalmente baixo custo. The EmployeeData classe incorretamente define uma propriedade que retorna uma cópia de uma matriz.

Imports System
Imports System.Collections.ObjectModel

Namespace Examples.DesignGuidelines.Properties
    Public Class EmployeeRecord

        Private employeeIdValue as Integer
        Private departmentValue as Integer

        Public Sub New()
        End Sub

        Public Sub New (id as Integer, departmentId as Integer)
            EmployeeId = id
            Department = departmentId
        End Sub

        Public Property Department as Integer
            Get 
                Return departmentValue
            End Get
            Set 
                departmentValue = value
            End Set
        End Property

        Public Property EmployeeId as Integer
            Get 
                Return employeeIdValue
            End Get
            Set 
                employeeIdValue = value
            End Set
        End Property
        Public Function Clone() as EmployeeRecord
            Return new EmployeeRecord(employeeIdValue, departmentValue)
        End Function
    End Class

Public Class EmployeeData

    Dim data as EmployeeRecord()
    Public Sub New(data as EmployeeRecord())
        Me.data = data
    End Sub
    Public ReadOnly Property Employees as EmployeeRecord()
        Get
            Dim newData as EmployeeRecord() = CopyEmployeeRecords()
            Return newData
        End Get
    End Property

    Private Function CopyEmployeeRecords() as EmployeeRecord()
        Dim newData(UBound(data)) as EmployeeRecord
        For i as Integer = 0 To UBound(data)
            newData(i) = data(i).Clone()
        Next i
        Console.WriteLine ("EmployeeData: cloned employee data.")
        Return newData
    End Function
End Class

Public Class RecordChecker
    Public Shared Function  FindEmployees( _
         dataSource as EmployeeData, _
         department as Integer) as Collection(Of Integer)

        Dim storage as Collection(Of Integer) = new Collection(Of Integer)()
        Console.WriteLine("Record checker: beginning search.")
        For i as Integer = 0 To UBound(dataSource.Employees)
            If dataSource.Employees(i).Department = department
                Console.WriteLine("Record checker: found match at {0}.", i)
                storage.Add(dataSource.Employees(i).EmployeeId)
                Console.WriteLine("Record checker: stored match at {0}.", i)
            Else 
                Console.WriteLine("Record checker: no match at {0}.", i)
            End If
        Next i
        Return storage
    End Function
End Class
    Public Class Tester
        Public Shared Sub Main()
            Dim records(2) as EmployeeRecord
            Dim r0 as EmployeeRecord = new EmployeeRecord()
            r0.EmployeeId = 1
            r0.Department = 100
            records(0) = r0
            Dim r1 as EmployeeRecord = new EmployeeRecord()
            r1.EmployeeId = 2
            r1.Department = 100
            records(1) = r1
            Dim r2 as EmployeeRecord = new EmployeeRecord()
            r2.EmployeeId = 3
            r2.Department = 101
            records(2) = r2
            Dim empData as EmployeeData = new EmployeeData(records)
            Dim hits as Collection(Of Integer)= _ 
                RecordChecker.FindEmployees(empData, 100)
            For Each i as Integer In hits
                Console.WriteLine("found employee {0}", i)
            Next i
        End Sub
    End Class
End Namespace
using System;
using System.Collections.ObjectModel;
namespace Examples.DesignGuidelines.Properties
{
    public class EmployeeRecord
    {
        private int employeeId;
        private int department;
        public EmployeeRecord()
        {
        }
        public  EmployeeRecord (int id, int departmentId)
        {
            EmployeeId = id;
            Department = departmentId;
        }
        public int Department
        {
            get {return department;}
            set {department = value;}
        }
        public int EmployeeId
        {
            get {return employeeId;}
            set {employeeId = value;}
        }
        public EmployeeRecord Clone()
        {
            return new EmployeeRecord(employeeId, department);
        }
    }

public class EmployeeData
{
    EmployeeRecord[] data;
    public EmployeeData(EmployeeRecord[] data)
    {
        this.data = data;
    }
    public EmployeeRecord[] Employees
    {
        get 
        {
            EmployeeRecord[] newData = CopyEmployeeRecords();
            return newData;
        }
    }
    EmployeeRecord[] CopyEmployeeRecords()
    {
        EmployeeRecord[] newData = new EmployeeRecord[data.Length];
        for(int i = 0; i< data.Length; i++)
        {
            newData[i] = data[i].Clone();
        }
        Console.WriteLine ("EmployeeData: cloned employee data.");
        return newData;
    }
}

public class RecordChecker
{
    public static Collection<int> FindEmployees(EmployeeData dataSource, 
             int department)
    {
        Collection<int> storage = new Collection<int>();
        Console.WriteLine("Record checker: beginning search.");
        for (int i = 0; i < dataSource.Employees.Length; i++)
        {
            if (dataSource.Employees[i].Department == department)
            {
                Console.WriteLine("Record checker: found match at {0}.", i);
                storage.Add(dataSource.Employees[i].EmployeeId);
                Console.WriteLine("Record checker: stored match at {0}.", i);
            }
            else 
            {
                Console.WriteLine("Record checker: no match at {0}.", i);
            }
        }
        return storage;
    }
}
    public class Tester
    {
        public static void Main()
        {
            EmployeeRecord[] records  = new EmployeeRecord[3];
            EmployeeRecord r0  = new EmployeeRecord();
            r0.EmployeeId = 1;
            r0.Department = 100;
            records[0] = r0;
            EmployeeRecord r1  = new EmployeeRecord();
            r1.EmployeeId = 2;
            r1.Department = 100;
            records[1] = r1;
            EmployeeRecord r2  = new EmployeeRecord();
            r2.EmployeeId = 3;
            r2.Department = 101;
            records[2] = r2;
            EmployeeData empData = new EmployeeData(records);
            Collection<int> hits = RecordChecker.FindEmployees(empData, 100);
            foreach (int i in hits)
            {
                Console.WriteLine("found employee {0}", i);
            }
        }
    }
}

Partes direitos autorais 2005 Microsoft Corporation. Todos os direitos reservados.

Partes direitos autorais Addison-Wesley Corporation. Todos os direitos reservados.

Para obter mais informações sobre diretrizes de design, consulte a "diretrizes de design do estrutura: Catálogo de convenções, idiomas e padrões para bibliotecas do .NET reutilizável"Krzysztof Cwalina e Brad Abrams, publicado pela Addison-Wesley, 2005.

Consulte também

Conceitos

Propriedade design

Outros recursos

Diretrizes de design de membro

Diretrizes de Design para desenvolvimento bibliotecas de classe