Как вы даете С# Auto-Property значение по умолчанию? Я либо использую конструктор, либо вернусь к старому синтаксису.
Использование конструктора:
class Person
{
public Person()
{
Name = "Default Name";
}
public string Name { get; set; }
}
Использование стандартного синтаксиса свойств (со значением по умолчанию)
private string name = "Default Name";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Есть ли лучший способ?
В С# 5 и более ранних версиях, чтобы дать автоматически реализованным свойствам значение по умолчанию, вы должны сделать это в конструкторе.
Возможность иметь инициализаторы свойств auto включена с С# 6.0. Синтаксис:
public int X { get; set; } = x; // C# 6 or higher
Отредактировано 1/2/15
С# 6:
С С# 6 вы можете инициализировать авто-свойства напрямую (наконец-то!), Теперь в ветке есть другие ответы, которые описывают это.
С# 5 и ниже:
Хотя предполагаемое использование атрибута не в том, чтобы фактически устанавливать значения свойств, вы можете использовать отражение, чтобы всегда устанавливать их в любом случае...
public class DefaultValuesTest
{
public DefaultValuesTest()
{
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
{
DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];
if (myAttribute != null)
{
property.SetValue(this, myAttribute.Value);
}
}
}
public void DoTest()
{
var db = DefaultValueBool;
var ds = DefaultValueString;
var di = DefaultValueInt;
}
[System.ComponentModel.DefaultValue(true)]
public bool DefaultValueBool { get; set; }
[System.ComponentModel.DefaultValue("Good")]
public string DefaultValueString { get; set; }
[System.ComponentModel.DefaultValue(27)]
public int DefaultValueInt { get; set; }
}
Когда вы встраиваете начальное значение для переменной, оно будет выполняться неявно в конструкторе.
Я бы сказал, что этот синтаксис был наилучшей практикой в С# до 5:
class Person
{
public Person()
{
//do anything before variable assignment
//assign initial values
Name = "Default Name";
//do anything after variable assignment
}
public string Name { get; set; }
}
Так как это дает вам четкое управление значениям порядка.
С С# 6 существует новый способ:
public string Name { get; set; } = "Default Name"
public Person(string name, int id) : this()
синтаксис public Person(string name, int id) : this()
, но у вас есть точка зрения. Это дает вам более точный контроль того, когда именно свойства инициализируются, за счет упрощения обслуживания встроенного параметра.
DefaultValueAttribute ТОЛЬКО работает в дизайнере vs. Он не будет инициализировать свойство для этого значения.
DefaultValueAttribute
не только для дизайнера. Однако «значение по умолчанию» не совпадает с «начальным значением».
Иногда я использую это, если я не хочу, чтобы он действительно был установлен и сохранялся в моем db:
class Person
{
private string _name;
public string Name
{
get
{
return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
}
set { _name = value; }
}
}
Очевидно, если это не строка, я могу сделать объект нулевым (double?, int?) и проверить, не null ли он, вернуть значение по умолчанию или вернуть значение, которое оно установило.
Затем я могу сделать чек в моем репозитории, чтобы увидеть, если он мой по умолчанию и не сохраняется, или сделать проверку бэкдор, чтобы увидеть истинный статус резервного значения, прежде чем сохранять.
Надеюсь, что это поможет!
return _name ?? "Default Name";
наверное даже понятнее что твой
Начиная с С# 6.0, мы можем назначить значение по умолчанию для автоматически реализованных свойств.
public string Name { get; set; } = "Some Name";
Мы также можем создать автоматическое свойство, доступное только для чтения, например:
public string Name { get; } = "Some Name";
Смотрите: С# 6: первые реакции, инициализаторы для автоматически реализованных свойств - Jon Skeet
Вы можете сделать это в самом объявлении Class
в заявлениях объявления свойств.
public class Coordinate
{
public int X { get; set; } = 34; // get or set auto-property with initializer
public int Y { get; } = 89; // read-only auto-property with initializer
public int Z { get; } // read-only auto-property with no initializer
// so it has to be initialized from constructor
public Coordinate() // .ctor()
{
Z = 42;
}
}
{ get; set; }
или { get; private set; }
как иначе установка значения будет заблокирована компилятором?
В версии С# (6.0) и выше вы можете:
Для свойств Readonly
public int ReadOnlyProp => 2;
Для обоих свойств Writable и Readable
public string PropTest { get; set; } = "test";
В текущей версии С# (7.0) вы можете сделать: (фрагмент скорее показывает, как вы можете использовать выражения с расширенными функциями get/set, чтобы сделать более компактным при использовании с полями поддержки)
private string label = "Default Value";
// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value;
}
маленький полный образец:
using System.ComponentModel;
private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
get { return bShowGroup; }
set { bShowGroup = value; }
}
DefaultValueAttribute
- просто подсказка сериализации, он не установит для ShowGroup
значение true
поскольку для любого логического значения по умолчанию установлено значение false
.
В дополнение к уже принятому ответу, для сценария, когда вы хотите определить свойство по умолчанию как функцию от других свойств, вы можете использовать нотацию тела выражения на С# 6.0 (и выше) для еще более элегантных и лаконичных конструкций, таких как:
public class Person{
public string FullName => $"{First} {Last}"; // expression body notation
public string First { get; set; } = "First";
public string Last { get; set; } = "Last";
}
Вы можете использовать вышеуказанное следующим образом
var p = new Person();
p.FullName; // First Last
p.First = "Jon";
p.Last = "Snow";
p.FullName; // Jon Snow
Чтобы использовать вышеуказанную нотацию "=>", свойство должно быть доступно только для чтения, и вы не используете ключевое слово get accessor.
Подробности на MSDN
Моим решением является использование настраиваемого атрибута, который инициализирует инициализацию значения по умолчанию константой или использует инициализатор типа свойства.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InstanceAttribute : Attribute
{
public bool IsConstructorCall { get; private set; }
public object[] Values { get; private set; }
public InstanceAttribute() : this(true) { }
public InstanceAttribute(object value) : this(false, value) { }
public InstanceAttribute(bool isConstructorCall, params object[] values)
{
IsConstructorCall = isConstructorCall;
Values = values ?? new object[0];
}
}
Чтобы использовать этот атрибут, необходимо наследовать класс из специального базового класса-инициализатора или использовать статический вспомогательный метод:
public abstract class DefaultValueInitializer
{
protected DefaultValueInitializer()
{
InitializeDefaultValues(this);
}
public static void InitializeDefaultValues(object obj)
{
var props = from prop in obj.GetType().GetProperties()
let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
where attrs.Any()
select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
foreach (var pair in props)
{
object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
? pair.Attr.Values[0]
: Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
pair.Property.SetValue(obj, value, null);
}
}
}
Пример использования:
public class Simple : DefaultValueInitializer
{
[Instance("StringValue")]
public string StringValue { get; set; }
[Instance]
public List<string> Items { get; set; }
[Instance(true, 3,4)]
public Point Point { get; set; }
}
public static void Main(string[] args)
{
var obj = new Simple
{
Items = {"Item1"}
};
Console.WriteLine(obj.Items[0]);
Console.WriteLine(obj.Point);
Console.WriteLine(obj.StringValue);
}
Вывод:
Item1
(X=3,Y=4)
StringValue
В С# 6 и выше вы можете просто использовать синтаксис:
public object Foo { get; set; } = bar;
Обратите внимание, что для свойства readonly
просто опускайте набор так:
public object Foo { get; } = bar;
Вы также можете назначить readonly
авто-свойства из конструктора.
До этого я ответил, как показано ниже.
Я бы не добавлял по умолчанию конструктор; оставьте это для динамических присвоений и избегайте наличия двух точек, в которых назначается переменная (т.е. тип по умолчанию и в конструкторе). Обычно я бы просто написал нормальное свойство в таких случаях.
Еще один вариант - сделать то, что делает ASP.Net и определять значения по умолчанию через атрибут:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
В конструкторе. Цель конструктора - инициализировать его членами данных.
private string name;
public string Name
{
get
{
if(name == null)
{
name = "Default Name";
}
return name;
}
set
{
name = value;
}
}
get;
с точкой с запятой (часто в сочетании с set;
), чтобы указать, что компилятор должен автоматически генерировать тело метода доступа get
.
public Class ClassName{
public int PropName{get;set;}
public ClassName{
PropName=0; //Default Value
}
}
Вы пытались использовать DefaultValueAttribute или ShouldSerialize и Reset в сочетании с конструктором? Я чувствую, что один из этих двух методов необходим, если вы создаете класс, который может отображаться на поверхности конструктора или в сетке свойств.
Используйте конструктор, потому что "Когда конструктор закончен, конструкция должна быть закончена". свойства похожи на состояния, которые хранятся ваши классы, если вам нужно было инициализировать состояние по умолчанию, вы сделали бы это в своем конструкторе.
Чтобы уточнить, да, вам нужно установить значения по умолчанию в конструкторе для объектов класса. Вам нужно будет убедиться, что конструктор существует с соответствующим модификатором доступа для построения, где он используется. Если объект не создается, например. он не имеет конструктора (например, статические методы), тогда значение по умолчанию может быть задано полем. Примером здесь является то, что сам объект будет создан только один раз, и вы не создадите его.
@Даррен Копп - хороший ответ, чистый и правильный. И, повторяю, вы можете написать конструкторы для абстрактных методов. Вам просто нужно получить к ним доступ из базового класса при написании конструктора:
Конструктор в базовом классе:
public BaseClassAbstract()
{
this.PropertyName = "Default Name";
}
Конструктор в Derived/Concrete/Sub-Class:
public SubClass() : base() { }
Дело здесь в том, что переменная экземпляра, взятая из базового класса, может похоронить имя вашего базового поля. Установка текущего значения объекта-объекта с помощью "this". позволит вам правильно сформировать ваш объект в отношении текущего экземпляра и требуемых уровней разрешений (модификаторы доступа), в которых вы его создаете.
Лично я не вижу смысла делать его собственностью вообще, если вы не собираетесь делать что-либо вообще за пределами авто-собственности. Просто оставьте это как поле. Преимущество инкапсуляции для этого элемента - просто красные сельди, потому что ничего не позади, чтобы инкапсулировать. Если вам когда-либо понадобится изменить базовую реализацию, вы по-прежнему можете реорганизовать их как свойства без нарушения какого-либо зависимого кода.
Хм... может быть, это будет вопрос его собственного вопроса позже
class Person
{
/// Gets/sets a value indicating whether auto
/// save of review layer is enabled or not
[System.ComponentModel.DefaultValue(true)]
public bool AutoSaveReviewLayer { get; set; }
}
Я думаю, что это сделало бы это для ya givng SomeFlag по умолчанию false.
private bool _SomeFlagSet = false;
public bool SomeFlag
{
get
{
if (!_SomeFlagSet)
SomeFlag = false;
return SomeFlag;
}
set
{
if (!_SomeFlagSet)
_SomeFlagSet = true;
SomeFlag = value;
}
}
Введите Prop и нажмите кнопку "TAB" и Visual Studio. Предложите вам следующий код,
public int MyProperty { get; set; }
после того, как вы сможете изменить модификатор, тип данных, имя и легко назначить набор и получить значения.
если вы должны использовать некоторую переменную в другом классе, вы можете использовать как follwing,
public static int MyProperty { get; set; }
в коде вы можете назначить переменную
MyProperty=1;
в другом классе вы можете использовать,
MessageBox.Show(Classname.MyProperty);
инициализируется в строке, использование конструкторов для инициализации - это плохая практика и приведет к более резким изменениям позже.