Em C #, o que diferencia um campo de uma propriedade e quando um campo deve ser usado em vez de uma propriedade?
Em C #, o que diferencia um campo de uma propriedade e quando um campo deve ser usado em vez de uma propriedade?
Respostas:
Propriedades expõem campos. Os campos devem (quase sempre) ser mantidos em sigilo para uma classe e acessados por meio de propriedades get e set. As propriedades fornecem um nível de abstração que permite alterar os campos sem afetar a maneira externa como eles são acessados pelas coisas que usam sua classe.
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
O @Kent ressalta que as Propriedades não precisam encapsular os campos, elas podem fazer um cálculo em outros campos ou servir a outros propósitos.
O @GSS salienta que você também pode executar outra lógica, como validação, quando uma propriedade é acessada, outro recurso útil.
string
, meu contrato é: atribua quaisquer caracteres até ~ 2bil. Se for uma propriedade DateTime
, meu contrato é: atribua quaisquer números dentro dos limites de DateTime, que eu possa procurar. Se o criador adicionar restrições aos levantadores, essas restrições não serão comunicadas. Mas se, em vez disso, o criador alterar o tipo de string
para Surname
, a nova classe Sobrenome comunicará as restrições e a propriedade public Surname LastName
não terá validação de setter. Além disso, Surname
é reutilizável.
Surname
, no meu exemplo, é reutilizável, você não precisa se preocupar em copiar / colar essas validações em um configurador de propriedades para outros locais no código. Também não é de admirar se a validação de um Sobrenome está em vários lugares, se você alguma vez fizer alterações nas regras de negócios para Apelidos. Confira no link eu postei sobre Valor Objects
Os princípios de programação orientada a objetos dizem que, o funcionamento interno de uma classe deve estar oculto do mundo exterior. Se você expõe um campo, está essencialmente expondo a implementação interna da classe. Portanto, agrupamos campos com Propriedades (ou métodos no caso de Java) para nos permitir alterar a implementação sem quebrar o código, dependendo de nós. Ver como podemos colocar lógica na Propriedade também nos permite executar a lógica de validação, etc., se precisarmos. O C # 3 tem a noção possivelmente confusa de autopropriedade. Isso nos permite simplesmente definir a Propriedade e o compilador C # 3 irá gerar o campo privado para nós.
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
public int myVar { get; set; }
realmente significa (e presumo que seja esse o motivo). pelo menos 50% dos acessos que essa pergunta recebe).
virtual
fazem parte da programação orientada a objetos.
virtual
OOP em si, no entanto. É uma ferramenta que permite o polimorfismo, que é uma das principais ferramentas que HABITA OOP. Porém, não é OOP por si só, e não há nada inerentemente OOP em uma propriedade pública pública. Também não contaria coisas como reflexão ou ligação de dados relacionadas ao OOP. Normalmente, eu não seria tão pedante quanto a isso, mas a resposta mencionou especificamente os princípios de OO como a força motriz por trás do exemplo de código, e não concordo com isso.
Uma diferença importante é que as interfaces podem ter propriedades, mas não campos. Isso, para mim, sublinha que as propriedades devem ser usadas para definir a interface pública de uma classe, enquanto os campos devem ser usados no funcionamento interno privado de uma classe. Como regra, raramente crio campos públicos e da mesma forma raramente crio propriedades não públicas.
Vou dar alguns exemplos de como usar propriedades que podem fazer as engrenagens girarem:
Usando Propriedades, você pode gerar um evento quando o valor da propriedade é alterado (também conhecido como PropertyChangedEvent) ou antes que o valor seja alterado para suportar o cancelamento.
Isso não é possível com (acesso direto a) campos.
public class Person {
private string _name;
public event EventHandler NameChanging;
public event EventHandler NameChanged;
public string Name{
get
{
return _name;
}
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
private void OnNameChanging(){
NameChanging?.Invoke(this,EventArgs.Empty);
}
private void OnNameChanged(){
NameChanged?.Invoke(this,EventArgs.Empty);
}
}
Como muitos deles explicaram com prós e contras técnicos de Properties
e Field
, é hora de entrar em exemplos em tempo real.
1. Propriedades permite definir o nível de acesso somente leitura
Considere o caso de dataTable.Rows.Count
e dataTable.Columns[i].Caption
. Eles vêm da classe DataTable
e ambos são públicos para nós. A diferença no nível de acesso a eles é que não podemos definir valor, dataTable.Rows.Count
mas podemos ler e escrever dataTable.Columns[i].Caption
. Isso é possível Field
? Não!!! Isso pode ser feito Properties
apenas.
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
2. Propriedades no PropertyGrid
Você pode ter trabalhado Button
no Visual Studio. Suas propriedades são mostradas da PropertyGrid
mesma forma Text
, Name
etc. Quando arrastamos e soltamos um botão, e quando clicamos nas propriedades, ele automaticamente encontra a classe Button
e os filtros Properties
e mostra isso em PropertyGrid
(onde PropertyGrid
não será exibido Field
mesmo que seja público).
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
Em PropertyGrid
, as propriedades Name
e Text
serão mostradas, mas não SomeProperty
. Por quê??? Porque Propriedades podem aceitar Atributos . Não aparece no caso em que [Browsable(false)]
é falso.
3. Pode executar instruções dentro de Propriedades
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
4. Somente propriedades podem ser usadas na fonte de ligação
Fonte de ligação nos ajuda a diminuir o número de linhas de código. Fields
não são aceitos por BindingSource
. Deveríamos usar Properties
para isso.
5. modo de depuração
Considere que estamos usando Field
para manter um valor. Em algum momento, precisamos depurar e verificar onde o valor está ficando nulo para esse campo. Será difícil fazer onde o número de linhas de código é superior a 1000. Nessas situações, podemos usar Property
e definir o modo de depuração dentro Property
.
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
Um campo é uma variável declarada diretamente em uma classe ou estrutura. Uma classe ou estrutura pode ter campos de instância ou campos estáticos ou ambos. Geralmente, você deve usar campos apenas para variáveis que tenham acessibilidade privada ou protegida . Os dados que sua classe expõe ao código do cliente devem ser fornecidos por meio de métodos, propriedades e indexadores. Ao usar essas construções para acesso indireto a campos internos, você pode proteger contra valores de entrada inválidos.
Uma propriedade é um membro que fornece um mecanismo flexível para ler, gravar ou calcular o valor de um campo particular. As propriedades podem ser usadas como se fossem membros de dados públicos, mas na verdade são métodos especiais chamados acessadores . Isso permite que os dados sejam acessados com facilidade e ainda ajuda a promover a segurança e a flexibilidade dos métodos . As propriedades permitem que uma classe exponha uma maneira pública de obter e definir valores, enquanto oculta o código de implementação ou verificação. Um acessador de propriedade get é usado para retornar o valor da propriedade e um acessador definido é usado para atribuir um novo valor.
As propriedades têm a principal vantagem de permitir que você altere a maneira como os dados em um objeto são acessados sem interromper sua interface pública. Por exemplo, se você precisar adicionar validação extra ou alterar um campo armazenado em um calculado, poderá fazê-lo facilmente se inicialmente expôs o campo como uma propriedade. Se você acabou de expor um campo diretamente, precisará alterar a interface pública da sua classe para adicionar a nova funcionalidade. Essa alteração quebraria os clientes existentes, exigindo que eles fossem recompilados antes que eles pudessem usar a nova versão do seu código.
Se você escrever uma biblioteca de classes projetada para amplo consumo (como o .NET Framework, que é usado por milhões de pessoas), isso pode ser um problema. No entanto, se você estiver escrevendo uma classe usada internamente em uma pequena base de código (digamos <= 50 K linhas), isso realmente não é grande coisa, porque ninguém seria afetado adversamente por suas alterações. Nesse caso, realmente se resume a preferência pessoal.
As propriedades suportam acesso assimétrico, ou seja, você pode ter um getter e um setter ou apenas um dos dois. Da mesma forma, as propriedades suportam acessibilidade individual para getter / setter. Os campos são sempre simétricos, ou seja, você sempre pode obter e definir o valor. Exceção a isso são campos somente leitura que obviamente não podem ser definidos após a inicialização.
As propriedades podem ser executadas por um período muito longo, ter efeitos colaterais e até gerar exceções. Os campos são rápidos, sem efeitos colaterais e nunca lançam exceções. Devido aos efeitos colaterais, uma propriedade pode retornar um valor diferente para cada chamada (como pode ser o caso de DateTime.Now, ou seja, DateTime.Now nem sempre é igual a DateTime.Now). Os campos sempre retornam o mesmo valor.
Os campos podem ser usados para parâmetros de saída / referência, as propriedades não. As propriedades suportam lógica adicional - isso pode ser usado para implementar o carregamento lento entre outras coisas.
As propriedades suportam um nível de abstração encapsulando o que significa obter / definir o valor.
Use propriedades na maioria dos casos, mas tente evitar efeitos colaterais.
No fundo, uma propriedade é compilada em métodos. Portanto, uma Name
propriedade é compilada em get_Name()
e set_Name(string value)
. Você pode ver isso se você estudar o código compilado. Portanto, há uma sobrecarga (muito) pequena de desempenho ao usá-los. Normalmente, você sempre usará uma propriedade se expor um campo para o exterior e frequentemente a usará internamente, se precisar validar o valor.
Quando você deseja que sua variável privada (campo) seja acessível ao objeto de sua classe de outras classes, é necessário criar propriedades para essas variáveis.
por exemplo, se eu tiver variáveis nomeadas como "id" e "name", que são privadas, mas pode haver uma situação em que essa variável seja necessária para a operação de leitura / gravação fora da classe. Nessa situação, a propriedade pode me ajudar a obter essa variável para leitura / gravação, dependendo do get / set definido para a propriedade. Uma propriedade pode ser somente leitura / gravação / gravação / leitura.
aqui está a demo
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
A segunda pergunta aqui, "quando um campo deve ser usado em vez de uma propriedade?", É abordada apenas brevemente nessa outra resposta e meio que também , mas sem muitos detalhes.
Em geral, todas as outras respostas são claras sobre o bom design: prefira expor propriedades ao invés de expor campos. Enquanto você provavelmente não vai se veja dizendo "uau, imagine como as coisas seriam piores se eu tivesse transformado esse campo em vez de uma propriedade", é muito mais raro pensar em uma situação em que você diria "uau, graças a Deus eu usei um campo aqui em vez de uma propriedade ".
Mas há uma vantagem que os campos têm sobre as propriedades, e essa é a capacidade delas de serem usadas como parâmetros "ref" / "out". Suponha que você tenha um método com a seguinte assinatura:
public void TransformPoint(ref double x, ref double y);
e suponha que você queira usar esse método para transformar uma matriz criada assim:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Aqui está a maneira mais rápida de fazer isso, já que X e Y são propriedades:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
E isso vai ser muito bom! A menos que você tenha medidas que provem o contrário, não há motivo para dar um fedor. Mas acredito que não é tecnicamente garantido que seja tão rápido quanto isso:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Fazendo algumas medições sozinho, a versão com campos leva cerca de 61% do tempo com a versão com propriedades (.NET 4.6, Windows 7, x64, modo de liberação, sem depurador conectado). Quanto mais caro o TransformPoint
método fica, menos pronunciada é a diferença. Para repetir isso, execute com a primeira linha comentada e com ela não comentada.
Mesmo se não houver benefícios de desempenho para os itens acima, há outros locais em que a capacidade de usar parâmetros ref e out pode ser benéfica, como ao chamar a família de métodos Interlocked ou Volatile . Nota: Caso isso seja novo para você, o Volatile é basicamente uma maneira de obter o mesmo comportamento fornecido pela volatile
palavra - chave. Assim volatile
, ele não resolve magicamente todos os problemas de segurança de threads, como o próprio nome sugere.
Definitivamente, não quero parecer que estou defendendo que você diga "ah, devo começar a expor campos em vez de propriedades". O ponto é que, se você precisar usar esses membros regularmente em chamadas que usam parâmetros "ref" ou "out", especialmente em algo que pode ser um tipo de valor simples, é improvável que você precise de algum elemento de valor agregado das propriedades, um argumento pode ser feito.
Embora os campos e as propriedades pareçam semelhantes, são dois elementos de linguagem completamente diferentes.
Os campos são o único mecanismo de armazenamento de dados no nível da classe. Os campos são conceitualmente variáveis no escopo da classe. Se você deseja armazenar alguns dados em instâncias de suas classes (objetos), precisará usar campos. Não há outra escolha. As propriedades não podem armazenar dados, embora possa parecer que eles são capazes de fazê-lo. Veja abaixo.
As propriedades, por outro lado, nunca armazenam dados. Eles são apenas os pares de métodos (obter e definir) que podem ser chamados sintaticamente de maneira semelhante aos campos e, na maioria dos casos, acessam campos (para leitura ou gravação), que é a fonte de alguma confusão. Mas como os métodos de propriedade são (com algumas limitações, como protótipo fixo) métodos C # regulares, eles podem fazer o que os métodos regulares podem fazer. Isso significa que eles podem ter 1000 linhas de código, podem gerar exceções, chamar outros métodos, podem ser virtuais, abstratos ou substituídos. O que torna as propriedades especiais é o fato de o compilador C # armazenar alguns metadados extras em assemblies que podem ser usados para procurar propriedades específicas - recurso amplamente usado.
Os métodos de propriedade Get e set possuem os seguintes protótipos.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
Portanto, significa que as propriedades podem ser 'emuladas' definindo um campo e 2 métodos correspondentes.
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
Essa emulação de propriedade é típica para linguagens de programação que não suportam propriedades - como C ++ padrão. Em C #, você sempre deve preferir propriedades como a maneira de acessar seus campos.
Como apenas os campos podem armazenar dados, isso significa que mais classe de campos contém, mais objetos de memória dessa classe serão consumidos. Por outro lado, adicionar novas propriedades a uma classe não aumenta os objetos dessa classe. Aqui está o exemplo.
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
Embora os métodos de propriedade possam fazer qualquer coisa, na maioria dos casos eles servem como uma maneira de acessar os campos dos objetos. Se você deseja tornar um campo acessível a outras classes, pode fazê-lo de duas maneiras.
Aqui está uma classe usando campos públicos.
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
Embora o código seja perfeitamente válido, do ponto de vista do design, ele tem várias desvantagens. Como os campos podem ser lidos e gravados, você não pode impedir que o usuário grave nos campos. Você pode aplicar a readonly
palavra-chave, mas dessa forma, você deve inicializar os campos somente leitura no construtor. Além do mais, nada impede que você armazene valores inválidos em seus campos.
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
O código é válido, todas as atribuições serão executadas, embora ilógicas. Age
tem um valor negativo, YearOfBirth
está distante no futuro e não corresponde à idade e FullName
é nulo. Com os campos, você não pode impedir que os usuários class Name
cometam esses erros.
Aqui está um código com propriedades que corrige esses problemas.
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
A versão atualizada da classe possui as seguintes vantagens.
FullName
e YearOfBirth
são verificados quanto a valores inválidos.Age
não é gravável. É calculado deYearOfBirth
ano atual.FullNameInUppercase
convertida FullName
em MAIÚSCULAS. Este é um exemplo um pouco artificial de uso de propriedade, em que propriedades são comumente usadas para apresentar valores de campo no formato mais apropriado para o usuário - por exemplo, usando a localidade atual em um numérico específico de DateTime
formato.Além disso, as propriedades podem ser definidas como virtuais ou substituídas - simplesmente porque são métodos .NET regulares. As mesmas regras se aplicam aos métodos de propriedade e aos métodos regulares.
O C # também suporta indexadores, que são as propriedades que possuem um parâmetro index nos métodos de propriedade. Aqui está o exemplo.
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
Como o C # 3.0 permite definir propriedades automáticas. Aqui está o exemplo.
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
Embora class AutoProps
contenha apenas propriedades (ou parece), ele pode armazenar 2 valores e o tamanho dos objetos dessa classe é igual a sizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 bytes.
A razão para isso é simples. Quando você define uma propriedade automática, o compilador C # gera código automático que contém o campo oculto e uma propriedade com métodos de propriedade acessando esse campo oculto. Aqui está o compilador de código produzido.
Aqui está um código gerado pelo ILSpy a partir do assembly compilado. A classe contém campos e propriedades ocultos gerados.
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}
Portanto, como você pode ver, o compilador ainda usa os campos para armazenar os valores - já que os campos são a única maneira de armazenar valores em objetos.
Portanto, como você pode ver, embora propriedades e campos tenham sintaxe de uso semelhante, eles são conceitos muito diferentes.Mesmo se você usar propriedades ou eventos automáticos - os campos ocultos são gerados pelo compilador onde os dados reais são armazenados.
Se você precisar tornar um valor de campo acessível ao mundo exterior (usuários de sua classe), não use campos públicos ou protegidos. Os campos sempre devem ser marcados como particulares. As propriedades permitem fazer verificações de valor, formatação, conversões etc. e geralmente tornam seu código mais seguro, mais legível e mais extensível para modificações futuras.
Se você usar primitivas de encadeamento, será forçado a usar campos. Propriedades podem quebrar seu código de thread. Além disso, o que Cory disse está correto.
(Realmente deve ser um comentário, mas não posso postar um comentário, por favor, desculpe se não for apropriado como um post).
Certa vez, trabalhei em um local onde a prática recomendada era usar campos públicos em vez de propriedades, quando o equivalente equivalente da propriedade teria acessado um campo, como em:
get { return _afield; }
set { _afield = value; }
Seu raciocínio era que o campo público poderia ser convertido em uma propriedade mais tarde no futuro, se necessário. Pareceu-me um pouco estranho na época. A julgar por esses posts, parece que muitos aqui também não concordariam. O que você poderia ter dito para tentar mudar as coisas?
Edit: Devo acrescentar que toda a base de código deste local foi compilada ao mesmo tempo, para que eles pensassem que alterar a interface pública das classes (alterando um campo público para uma propriedade) não era um problema.
Tecnicamente, não acho que exista uma diferença, porque as propriedades são apenas wrappers em torno dos campos criados pelo usuário ou criados automaticamente pelo compilador. O objetivo das propriedades é impor o encapsulamento e oferecer um recurso leve e semelhante ao método. É apenas uma prática ruim declarar campos como públicos, mas não há nenhum problema.
Campos são variáveis de membros comuns ou instâncias de membros de uma classe. Propriedades são uma abstração para obter e definir seus valores . As propriedades também são chamadas de acessadores porque oferecem uma maneira de alterar e recuperar um campo se você expuser um campo na classe como privado. Geralmente, você deve declarar suas variáveis de membro privadas e, em seguida, declarar ou definir propriedades para elas.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
As propriedades encapsulam campos, permitindo que você execute um processamento adicional no valor a ser definido ou recuperado. Geralmente, é um exagero usar propriedades se você não estiver executando nenhum pré ou pós-processamento no valor do campo.
Na IMO, as propriedades são apenas os pares de funções / métodos / interfaces "SetXXX ()" "GetXXX ()" que usamos anteriormente, mas são mais concisos e elegantes.
Tradicionalmente, os campos privados são definidos pelos métodos getter e setter. Por uma questão de menos código, você pode usar propriedades para definir campos.
quando você tem uma classe que é "Carro". As propriedades são cor, forma ..
Onde os campos são variáveis definidas no escopo de uma classe.
Da Wikipedia - Programação orientada a objetos :
A programação orientada a objetos (OOP) é um paradigma de programação baseado no conceito de "objetos", que são estruturas de dados que contêm dados, na forma de campos , geralmente conhecidos como atributos; e código, na forma de procedimentos, geralmente conhecidos como métodos . (enfase adicionada)
Na verdade, as propriedades fazem parte do comportamento de um objeto, mas são projetadas para dar aos consumidores do objeto a ilusão / abstração de trabalhar com os dados do objeto.
Meu design de um campo é que um campo precisa ser modificado apenas por seu pai, daí a classe. Resultado, a variável se torna privada, para que eu possa dar o direito de ler as classes / métodos fora, passo pelo sistema de propriedades apenas com o Get. O campo é recuperado pela propriedade e somente leitura! Se você quiser modificá-lo, precisará passar por métodos (por exemplo, o construtor) e acho que, graças a essa maneira de protegê-lo, temos um melhor controle sobre nosso código, porque "flangeamos". Pode-se muito bem sempre colocar tudo em público, então todos os casos possíveis, a noção de variáveis / métodos / classes etc ... na minha opinião é apenas uma ajuda para o desenvolvimento, manutenção do código. Por exemplo, se uma pessoa retoma um código com campos públicos, ela pode fazer qualquer coisa e, portanto, coisas "ilógicas" em relação ao objetivo, a lógica do motivo pelo qual o código foi escrito. É o meu ponto de vista.
Quando eu uso um campo privado de modelo clássico / propriedades públicas somente leitura, para 10 campos privados, eu devo escrever 10 propriedades públicas! O código pode ser muito grande mais rápido. Descobri o setter privado e agora só uso propriedades públicas com um setter privado. O levantador cria em segundo plano um campo privado.
Por isso, meu antigo estilo de programação clássico era:
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
Meu novo estilo de programação:
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
Pense bem: você tem um quarto e uma porta para entrar neste quarto. Se você quiser verificar como quem está entrando e proteger seu quarto, use as propriedades, caso contrário elas não terão nenhuma porta e todas entrarão facilmente sem regulamentação
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
As pessoas estão entrando na seçãoOne muito facilmente, não houve nenhuma verificação
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
Agora você conferiu a pessoa e sabe se ela tem algo de ruim com ela
Campos são as variáveis nas classes. Campos são os dados que você pode encapsular através do uso de modificadores de acesso.
As propriedades são semelhantes a Fields, pois definem estados e dados associados a um objeto.
Ao contrário de um campo, uma propriedade possui uma sintaxe especial que controla como uma pessoa lê e grava os dados, conhecidos como operadores get e set. A lógica do conjunto geralmente pode ser usada para fazer a validação.
As propriedades são um tipo especial de membro da classe. Nas propriedades, usamos um método Set ou Get predefinido. Eles usam acessadores através dos quais podemos ler, escrever ou alterar os valores dos campos particulares.
Por exemplo, vamos usar uma classe chamada Employee
, com campos particulares para nome, idade e Employee_Id. Não podemos acessar esses campos de fora da classe, mas podemos acessar esses campos particulares por meio de propriedades.
Por que usamos propriedades?
Tornar público o campo da classe e expô-lo é arriscado, pois você não terá controle sobre o que é atribuído e devolvido.
Para entender isso claramente com um exemplo, vamos dar uma aula de aluno que tenha ID, marca de passagem, nome. Agora, neste exemplo, algum problema com o campo público
Para remover esse problema, usamos o método Get e set.
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
Agora vamos dar um exemplo do método get e set
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
Informações adicionais: por padrão, os acessadores de obtenção e configuração são tão acessíveis quanto a própria propriedade. Você pode controlar / restringir a acessibilidade do acessador individualmente (para obter e definir) aplicando modificadores de acesso mais restritivos.
Exemplo:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Aqui, get ainda é acessado publicamente (como a propriedade é pública), mas set está protegido (um especificador de acesso mais restrito).
Propriedades são usadas para expor o campo. Eles usam acessadores (set, get) através dos quais os valores dos campos privados podem ser lidos, gravados ou manipulados.
Propriedades não nomeiam os locais de armazenamento. Em vez disso, eles têm acessadores que lêem, gravam ou calculam seus valores.
Usando propriedades, podemos definir a validação do tipo de dados que é definido em um campo.
Por exemplo, temos a idade do campo inteiro privado em que devemos permitir valores positivos, pois a idade não pode ser negativa.
Podemos fazer isso de duas maneiras, usando getter e setters e usando a propriedade
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
Propriedade implementada automaticamente se não fizermos lógica em obter e configurar acessadores, podemos usar a propriedade implementada automaticamente.
Quando você usa compilações de propriedades implementadas automaticamente, cria um campo privado e anônimo que só pode ser acessado por meio de acessadores get e set.
public int Age{get;set;}
Propriedades abstratas Uma classe abstrata pode ter uma propriedade abstrata, que deve ser implementada na classe derivada
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Podemos definir uma propriedade em particular. Nisto podemos definir em particular a propriedade auto (definida com na classe)
public int MyProperty
{
get; private set;
}
Você pode conseguir o mesmo com este código. Nesse conjunto de propriedades, o recurso não está disponível, pois precisamos definir o valor para o campo diretamente.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
A grande maioria dos casos será um nome de propriedade que você acessa em vez de um nome de variável ( campo ). O motivo disso é que é considerada uma boa prática no .NET e no C # em particular para proteger todos os dados de uma classe. , seja uma variável de instância ou estática (variável de classe), porque está associada a uma classe.
Proteja todas essas variáveis com propriedades correspondentes que permitem definir, definir e obter acessadores e fazer coisas como validação ao manipular essas partes de dados.
Mas em outros casos, como a classe Math (espaço de nome System), existem algumas propriedades estáticas que são incorporadas à classe. um dos quais é a constante matemática PI
por exemplo. Math.PI
e como o PI é um dado bem definido, não precisamos ter várias cópias do PI, sempre terá o mesmo valor. Portanto, variáveis estáticas às vezes são usadas para compartilhar dados entre objetos de uma classe, mas elas também são comumente usadas para informações constantes, nas quais você só precisa de uma cópia de uma parte dos dados.