Если и get, и set являются обязательными в автоматических свойствах C #, зачем мне беспокоиться об указании "get; set;" вообще?
Автоматические свойства C # - зачем писать get; набор;?
Ответы (9)
ОШИБКА: свойство или индексатор нельзя передать как параметр 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, например {получить; private set;} делает get общедоступным, а набор - частным для объявляющего класса.
Потому что вам может понадобиться свойство только для чтения:
public int Foo { get; private set; }
Или свойство только для записи:
public int Foo { private get; set; }
Просто подумал, что поделюсь своими выводами по этой теме.
Кодирование свойства, подобного следующему, представляет собой вызов ярлыка .net 3.0 «автоматически реализованное свойство».
public int MyProperty { get; set; }
Это сэкономит вам время на вводе текста. Длинный способ объявления свойства выглядит следующим образом:
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; }
}
Когда вы используете «автоматически реализуемое свойство», компилятор генерирует код для подключения к получению и установки некоторого «k_BackingField». Ниже представлен дизассемблированный код с использованием Reflector.
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
[CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
дизассемблированный код C # из IL
Также подключает метод для установщика и получателя.
[CompilerGenerated]
public void set_MyProperty(int value)
{
this.<MyProperty>k__BackingField = value;
}
[CompilerGenerated]
public int get_MyProperty()
{
return this.<MyProperty>k__BackingField;
}
дизассемблированный код C # из IL
Когда вы объявляете автоматически реализуемое свойство только для чтения, устанавливая для установщика значение private:
public int MyProperty { get; private set; }
Все, что компилятор делает, помечает "набор" как частный. То же самое говорят методы установки и получения.
public int MyProperty
{
[CompilerGenerated]
get
{
return this.<MyProperty>k__BackingField;
}
private [CompilerGenerated]
set
{
this.<MyProperty>k__BackingField = value;
}
}
дизассемблированный код C # из 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;
}
дизассемблированный код C # из IL
Потому что вам нужен способ отличить его от простых полей.
Также полезно иметь разные модификаторы доступа, например
public int MyProperty { get; private set; }
Компилятор должен знать, хотите ли вы, чтобы он генерировал геттер и / или сеттер или, возможно, объявлял поле.
Если бы у свойства не было средств доступа, как бы компилятор отделил его от поля? А что бы его отделить от поля?
Что ж, очевидно, вам нужен способ устранения неоднозначности между полями и свойствами. Но действительно ли необходимы обязательные ключевые слова? Например, ясно, что эти два объявления разные:
public int Foo;
public int Bar { }
Это могло сработать. То есть это синтаксис, который компилятор мог бы понять.
Но тогда вы попадаете в ситуацию, когда пустой блок имеет семантическое значение. Это кажется ненадежным.
Поскольку никто не упомянул об этом ... вы можете сделать автоматическое свойство виртуальным и переопределить его:
public virtual int Property { get; set; }
Если бы не было get / set, как бы это было переопределено? Обратите внимание, что вам разрешено переопределять получатель, а не сеттер:
public override int Property { get { return int.MinValue; } }
Кроме того, поскольку начиная с C # 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's good and intended.
// But...
p.Method();
Console.WriteLine(p);
}
}
Другие интересные новости о C # 6.0 доступны в виде официального превью видео здесь.