Если оба метода get и set являются обязательными в автоматических свойствах С#, почему я должен беспокоиться о том, чтобы указать "get; set;" на всех?
С# Автоматические свойства - зачем мне писать "get; set;"?
Ответ 1
ОШИБКА: свойство или индекс не могут быть переданы как параметр out или ref
Если вы не указали {get; set;}
, тогда компилятор не узнает, является ли это полем или свойством.
Это важно, потому что, когда они "выглядят" одинаково, компилятор рассматривает их по-разному. например Вызов "InitAnInt" в свойстве вызывает ошибку.
class Test
{
public int n;
public int i { get; set; }
public void InitAnInt(out int p)
{
p = 100;
}
public Test()
{
InitAnInt(out n); // This is OK
InitAnInt(out i); // ERROR: A property or indexer may not be passed
// as an out or ref parameter
}
}
Вам не следует создавать общедоступные поля/переменные в классах, вы никогда не знаете, когда захотите их изменить, чтобы получить и установить аксессоры, а затем вы не знаете, какой код вы собираетесь сломать, особенно если у вас есть клиенты, которые работают против вашего API.
Также вы можете иметь разные модификаторы доступа для get и set, например. {получить; закрытый набор;} делает публикацию public и набор закрытым для класса объявления.
Ответ 2
Поскольку вам может понадобиться свойство только для чтения:
public int Foo { get; private set; }
Или свойство Write-only:
public int Foo { private get; set; }
Ответ 3
Потому что вам нужно каким-то образом отличить его от простых полей.
Также полезно иметь разные модификаторы доступа, например.
public int MyProperty { get; private set; }
Ответ 4
Просто подумал, что поделился бы своими выводами по этой теме.
Кодирование свойства, подобного следующему, представляет собой ярлык .net 3.0 " автоматически реализованное свойство".
public int MyProperty { get; set; }
Это экономит вас при наборе текста. Длинный способ объявления свойства выглядит следующим образом:
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
Когда вы используете "автоматически реализованное свойство", компилятор генерирует код для подключения get и устанавливается на некоторый "k_BackingField". Ниже представлен дизассемблированный код с использованием Reflector.
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
[CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
дизассемблированный код С# из IL
Также подключает метод для установщика и получателя.
[CompilerGenerated]
public void set_MyProperty(int value)
{
this.<MyProperty>k__BackingField = value;
}
[CompilerGenerated]
public int get_MyProperty()
{
return this.<MyProperty>k__BackingField;
}
дизассемблированный код С# из IL
Когда вы объявляете только автообновляемое свойство read only, установив приватный параметр setter:
public int MyProperty { get; private set; }
Все компиляторы делают флаг установлен закрытым. Метод setter и getter говорит то же самое.
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
private [CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
дизассемблированный код С# из IL
Итак, я не уверен, почему в структуре требуются как get; и установить; на авто-реализованное свойство. Они могли бы просто не писать метод set и setter, если он не был поставлен. Но может быть проблема с уровнем компилятора, которая делает это сложным, я не знаю.
Если вы посмотрите на длинный путь объявления свойства только для чтения:
public int myProperty = 0;
public int MyProperty
{
get { return myProperty; }
}
И затем посмотрите на разобранный код. Установки нет вообще.
public int Test2
{
get
{
return this._test;
}
}
public int get_Test2()
{
return this._test;
}
дизассемблированный код С# из IL
Ответ 5
Компилятор должен знать, хотите ли вы, чтобы он генерировал getter и/или сеттер, или, возможно, объявлял поле.
Ответ 6
Если у объекта не было доступа, каким образом компилятор отделит его от поля? И что бы отделить его от поля?
Ответ 7
Ну, очевидно, вам нужен способ устранения неоднозначности полей и свойств. Но требуются ли ключевые слова действительно необходимые? Например, ясно, что эти два объявления различны:
public int Foo;
public int Bar { }
Это может сработать. То есть, это синтаксис, который мог бы понять компилятор.
Но тогда вы попадаете в ситуацию, когда пустой блок имеет смысловое значение. Это кажется неустойчивым.
Ответ 8
Поскольку никто не упомянул об этом... вы могли бы сделать авто-свойство виртуальным и переопределить его:
public virtual int Property { get; set; }
Если бы не было get/set, как бы это было переопределено? Обратите внимание, что вам разрешено переопределить получателя, а не установщика:
public override int Property { get { return int.MinValue; } }
Ответ 9
Кроме того, поскольку С# 6.0 (в Visual Studio 2015, во время этого ответа, доступного в версии Ultimate Preview), вы можете реализовать истинное свойство только для чтения:
public string Name { get; }
public string Name { get; } = "This won't change even internally";
... в отличие от существующего в настоящее время несовершенного обходного пути с открытой парней-получателем/частным сеттером:
public string Name { get; private set; }
public Constructor() { Name="As initialised"; }
public void Method() { Name="This might be changed internally. By mistake. Or not."; }
Пример приведенного ниже (скомпилированный и исполняемый онлайн здесь).
using System;
public class Propertier {
public string ReadOnlyPlease { get; private set; }
public Propertier() { ReadOnlyPlease="As initialised"; }
public void Method() { ReadOnlyPlease="This might be changed internally"; }
public override string ToString() { return String.Format("[{0}]",ReadOnlyPlease); }
}
public class Program {
static void Main() {
Propertier p=new Propertier();
Console.WriteLine(p);
// p.ReadOnlyPlease="Changing externally!";
// Console.WriteLine(p);
// error CS0272: The property or indexer `Propertier.ReadOnlyPlease' cannot be used in this context because the set accessor is inaccessible
// That good and intended.
// But...
p.Method();
Console.WriteLine(p);
}
}
Другие вкусные новости о С# 6.0 доступны в качестве официального предварительного просмотра здесь.