When refactoring code, I come up with instances like the following
private string _property = string.Empty;
public string Property
{
set { _property = value ?? string.Empty); }
}
Later on in a method I see the following:
if (_property != null)
{
//...
}
Assuming that _property is only set by the setter of Property, is this code redundant?
I.e is there any way, through reflection wizardry or other methods that _property can ever be null?
Assuming that _property is only set by the setter of Property, is this
code redundant?
Exactly, it is redundant. This is the actual purpose of Properties. We shouldn't access the fields of a class directly. We should access them using a Property. So in the corresponding setter, we can embed any logic and we can rest assure that each time we try to set a value this logic would be verified once more.This argument holds even for the methods of a class. In a method we must use the properties and not the actual fields. Furthermore, when we want to read the value of a field, we should make use of the corresponding getter.
In general, properties enhances the concept of encapsulation, which is one of the pillars of object oriented programming OOP.
Many times there isn't any logic that should be applied when we want to set a value. Take for instance the following example:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have declared a class for representing a Customer. A Customer object should have three properties an Id, a FirstName and a LastName.
An immediate question, when someones read this class is why should someone make use of properties here?
The answer is again the same, they provide a mechanism of encapsulation. But let's consider how can this help us in the long run. Let's say that one day someone decides that the first name of a customer should be a string of length less than 20. If the above class had been declared as below:
public class Customer
{
public int Id;
public string FirstName;
public string LastName;
}
then we should check for the length of FirstName in each instance we had created ! Otherwise, if we had picked the declaration with the properties, we could just easily make use of Data Annotations
public class Customer
{
public int Id { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
public string LastName { get; set; }
}
and that's it. Another approach it could be the following:
public class Customer
{
public int Id { get; set; }
private string firstName;
public string FirstName
{
get { return firstName }
set
{
if(value!=null && value.length<20)
{
firstName = value;
}
else
{
throw new ArgumentException("The first name must have at maxium 20 characters", "value");
}
}
}
public string LastName { get; set; }
}
Consider both of the above approaches with having to revisit all your codebase and make this check. It's crystal clear that properties win.
Yes, it is possible through reflection. Nevertheless, I wouldn't worry about reflection -- people using reflection to defeat the design of your class is not something I worry about.
There is, however, something I do worry about: the phrase "Assuming that _property is only set by the setter of Property" is key. You are preventing users of your class from setting property to null.
You do not prevent, however, yourself or some other maintainer of your class from forgetting to only use the property INSIDE your class. In fact, your example has some one checking the field from inside the class rather than the property itself.... which means that, within your class, access comes from both the field and the property.
In most cases (where the problem could only come from inside the class) I would use an assertion and assert the field is not null.
If I really, really, really wanted to make sure that it wasn't null (barring reflection or people hell-bent on breaking things), you could try something like this:
internal class Program
{
static void Main()
{
string example = "Spencer the Cat";
UsesNeverNull neverNullUser = new UsesNeverNull(example);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = null;
Debug.Assert(neverNullUser.TheString != null);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = "Maximus the Bird";
Console.WriteLine(neverNullUser.TheString);
}
}
public class UsesNeverNull
{
public string TheString
{
get { return _stringValue.Value; }
set { _stringValue.Value = value; }
}
public UsesNeverNull(string s)
{
TheString = s;
}
private readonly NeverNull<string> _stringValue = new NeverNull<string>(string.Empty, str => str ?? string.Empty);
}
public class NeverNull<T> where T : class
{
public NeverNull(T initialValue, Func<T, T> nullProtector)
{
if (nullProtector == null)
{
var ex = new ArgumentNullException(nameof(nullProtector));
throw ex;
}
_value = nullProtector(initialValue);
_nullProtector = nullProtector;
}
public T Value
{
get { return _nullProtector(_value); }
set { _value = _nullProtector(value); }
}
private T _value;
private readonly Func<T, T> _nullProtector;
}
It is basically redundant. However, if it were mission critical or if for some reason it caused terrible side effects, it could remain. It is hard to tell, but part of your question was "can reflection change this value to null" to which the answer is yes and can be seen here in this linqpad demo
void Main()
{
var test = new Test();
test.Property = "5";
Console.WriteLine(test.Property);//5
FieldInfo fieldInfo = test.GetType().GetField("_property",BindingFlags.NonPublic | BindingFlags.Instance);
fieldInfo.SetValue(test, null);
Console.WriteLine(test.Property);//null
}
public class Test
{
private string _property = string.Empty;
public string Property
{
get { return _property; }
set { _property = value ?? string.Empty; }
}
}
I know this question is old, but look, I needed that one of my string properties never came up in null.
So I did this, and It worked for me
public string Operation { get; set; } = string.Empty;
In this way the default value is a string empty, but never null.
Related
How do you give a C# auto-property an initial value?
I either use the constructor, or revert to the old syntax.
Using the Constructor:
class Person
{
public Person()
{
Name = "Initial Name";
}
public string Name { get; set; }
}
Using normal property syntax (with an initial value)
private string name = "Initial Name";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Is there a better way?
In C# 5 and earlier, to give auto implemented properties an initial value, you have to do it in a constructor.
Since C# 6.0, you can specify initial value in-line. The syntax is:
public int X { get; set; } = x; // C# 6 or higher
DefaultValueAttribute is intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in designed object, initial value is the default value).
At compile time DefaultValueAttribute will not impact the generated IL and it will not be read to initialize the property to that value (see DefaultValue attribute is not working with my Auto Property).
Example of attributes that impact the IL are ThreadStaticAttribute, CallerMemberNameAttribute, ...
Edited on 1/2/15
C# 6 :
With C# 6 you can initialize auto-properties directly (finally!), there are now other answers that describe that.
C# 5 and below:
Though the intended use of the attribute is not to actually set the values of the properties, you can use reflection to always set them anyway...
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; }
}
When you inline an initial value for a variable it will be done implicitly in the constructor anyway.
I would argue that this syntax was best practice in C# up to 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; }
}
As this gives you clear control of the order values are assigned.
As of C#6 there is a new way:
public string Name { get; set; } = "Default Name";
Sometimes I use this, if I don't want it to be actually set and persisted in my db:
class Person
{
private string _name;
public string Name
{
get
{
return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
}
set { _name = value; }
}
}
Obviously if it's not a string then I might make the object nullable ( double?, int? ) and check if it's null, return a default, or return the value it's set to.
Then I can make a check in my repository to see if it's my default and not persist, or make a backdoor check in to see the true status of the backing value, before saving.
In C# 6.0 this is a breeze!
You can do it in the Class declaration itself, in the property declaration statements.
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;
}
}
Starting with C# 6.0, We can assign default value to auto-implemented properties.
public string Name { get; set; } = "Some Name";
We can also create read-only auto implemented property like:
public string Name { get; } = "Some Name";
See: C# 6: First reactions , Initializers for automatically implemented properties - By Jon Skeet
In Version of C# (6.0) & greater, you can do :
For Readonly properties
public int ReadOnlyProp => 2;
For both Writable & Readable properties
public string PropTest { get; set; } = "test";
In current Version of C# (7.0), you can do : (The snippet rather displays how you can use expression bodied get/set accessors to make is more compact when using with backing fields)
private string label = "Default Value";
// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value;
}
In C# 9.0 was added support of init keyword - very useful and extremly sophisticated way for declaration read-only auto-properties:
Declare:
class Person
{
public string Name { get; init; } = "Anonymous user";
}
~Enjoy~ Use:
// 1. Person with default name
var anonymous = new Person();
Console.WriteLine($"Hello, {anonymous.Name}!");
// > Hello, Anonymous user!
// 2. Person with assigned value
var me = new Person { Name = "#codez0mb1e"};
Console.WriteLine($"Hello, {me.Name}!");
// > Hello, #codez0mb1e!
// 3. Attempt to re-assignment Name
me.Name = "My fake";
// > Compilation error: Init-only property can only be assigned in an object initializer
In addition to the answer already accepted, for the scenario when you want to define a default property as a function of other properties you can use expression body notation on C#6.0 (and higher) for even more elegant and concise constructs like:
public class Person{
public string FullName => $"{First} {Last}"; // expression body notation
public string First { get; set; } = "First";
public string Last { get; set; } = "Last";
}
You can use the above in the following fashion
var p = new Person();
p.FullName; // First Last
p.First = "Jon";
p.Last = "Snow";
p.FullName; // Jon Snow
In order to be able to use the above "=>" notation, the property must be read only, and you do not use the get accessor keyword.
Details on MSDN
In C# 6 and above you can simply use the syntax:
public object Foo { get; set; } = bar;
Note that to have a readonly property simply omit the set, as so:
public object Foo { get; } = bar;
You can also assign readonly auto-properties from the constructor.
Prior to this I responded as below.
I'd avoid adding a default to the constructor; leave that for dynamic assignments and avoid having two points at which the variable is assigned (i.e. the type default and in the constructor). Typically I'd simply write a normal property in such cases.
One other option is to do what ASP.Net does and define defaults via an attribute:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
My solution is to use a custom attribute that provides default value property initialization by constant or using property type initializer.
[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];
}
}
To use this attribute it's necessary to inherit a class from special base class-initializer or use a static helper method:
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);
}
}
}
Usage example:
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);
}
Output:
Item1
(X=3,Y=4)
StringValue
little complete sample:
using System.ComponentModel;
private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
get { return bShowGroup; }
set { bShowGroup = value; }
}
You can simple put like this
public sealed class Employee
{
public int Id { get; set; } = 101;
}
In the constructor. The constructor's purpose is to initialized it's data members.
private string name;
public string Name
{
get
{
if(name == null)
{
name = "Default Name";
}
return name;
}
set
{
name = value;
}
}
Have you tried using the DefaultValueAttribute or ShouldSerialize and Reset methods in conjunction with the constructor? I feel like one of these two methods is necessary if you're making a class that might show up on the designer surface or in a property grid.
Use the constructor because "When the constructor is finished, Construction should be finished". properties are like states your classes hold, if you had to initialize a default state, you would do that in your constructor.
To clarify, yes, you need to set default values in the constructor for class derived objects. You will need to ensure the constructor exists with the proper access modifier for construction where used. If the object is not instantiated, e.g. it has no constructor (e.g. static methods) then the default value can be set by the field. The reasoning here is that the object itself will be created only once and you do not instantiate it.
#Darren Kopp - good answer, clean, and correct. And to reiterate, you CAN write constructors for Abstract methods. You just need to access them from the base class when writing the constructor:
Constructor at Base Class:
public BaseClassAbstract()
{
this.PropertyName = "Default Name";
}
Constructor at Derived / Concrete / Sub-Class:
public SubClass() : base() { }
The point here is that the instance variable drawn from the base class may bury your base field name. Setting the current instantiated object value using "this." will allow you to correctly form your object with respect to the current instance and required permission levels (access modifiers) where you are instantiating it.
public Class ClassName{
public int PropName{get;set;}
public ClassName{
PropName=0; //Default Value
}
}
This is old now, and my position has changed. I'm leaving the original answer for posterity only.
Personally, I don't see the point of making it a property at all if you're not going to do anything at all beyond the auto-property. Just leave it as a field. The encapsulation benefit for these item are just red herrings, because there's nothing behind them to encapsulate. If you ever need to change the underlying implementation you're still free to refactor them as properties without breaking any dependent code.
Hmm... maybe this will be the subject of it's own question later
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; }
}
I know this is an old question, but it came up when I was looking for how to have a default value that gets inherited with the option to override, I came up with
//base class
public class Car
{
public virtual string FuelUnits
{
get { return "gasoline in gallons"; }
protected set { }
}
}
//derived
public class Tesla : Car
{
public override string FuelUnits => "ampere hour";
}
I think this would do it for ya givng SomeFlag a default of false.
private bool _SomeFlagSet = false;
public bool SomeFlag
{
get
{
if (!_SomeFlagSet)
SomeFlag = false;
return SomeFlag;
}
set
{
if (!_SomeFlagSet)
_SomeFlagSet = true;
SomeFlag = value;
}
}
How do you give a C# auto-property an initial value?
I either use the constructor, or revert to the old syntax.
Using the Constructor:
class Person
{
public Person()
{
Name = "Initial Name";
}
public string Name { get; set; }
}
Using normal property syntax (with an initial value)
private string name = "Initial Name";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Is there a better way?
In C# 5 and earlier, to give auto implemented properties an initial value, you have to do it in a constructor.
Since C# 6.0, you can specify initial value in-line. The syntax is:
public int X { get; set; } = x; // C# 6 or higher
DefaultValueAttribute is intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in designed object, initial value is the default value).
At compile time DefaultValueAttribute will not impact the generated IL and it will not be read to initialize the property to that value (see DefaultValue attribute is not working with my Auto Property).
Example of attributes that impact the IL are ThreadStaticAttribute, CallerMemberNameAttribute, ...
Edited on 1/2/15
C# 6 :
With C# 6 you can initialize auto-properties directly (finally!), there are now other answers that describe that.
C# 5 and below:
Though the intended use of the attribute is not to actually set the values of the properties, you can use reflection to always set them anyway...
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; }
}
When you inline an initial value for a variable it will be done implicitly in the constructor anyway.
I would argue that this syntax was best practice in C# up to 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; }
}
As this gives you clear control of the order values are assigned.
As of C#6 there is a new way:
public string Name { get; set; } = "Default Name";
Sometimes I use this, if I don't want it to be actually set and persisted in my db:
class Person
{
private string _name;
public string Name
{
get
{
return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
}
set { _name = value; }
}
}
Obviously if it's not a string then I might make the object nullable ( double?, int? ) and check if it's null, return a default, or return the value it's set to.
Then I can make a check in my repository to see if it's my default and not persist, or make a backdoor check in to see the true status of the backing value, before saving.
In C# 6.0 this is a breeze!
You can do it in the Class declaration itself, in the property declaration statements.
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;
}
}
Starting with C# 6.0, We can assign default value to auto-implemented properties.
public string Name { get; set; } = "Some Name";
We can also create read-only auto implemented property like:
public string Name { get; } = "Some Name";
See: C# 6: First reactions , Initializers for automatically implemented properties - By Jon Skeet
In Version of C# (6.0) & greater, you can do :
For Readonly properties
public int ReadOnlyProp => 2;
For both Writable & Readable properties
public string PropTest { get; set; } = "test";
In current Version of C# (7.0), you can do : (The snippet rather displays how you can use expression bodied get/set accessors to make is more compact when using with backing fields)
private string label = "Default Value";
// Expression-bodied get / set accessors.
public string Label
{
get => label;
set => this.label = value;
}
In C# 9.0 was added support of init keyword - very useful and extremly sophisticated way for declaration read-only auto-properties:
Declare:
class Person
{
public string Name { get; init; } = "Anonymous user";
}
~Enjoy~ Use:
// 1. Person with default name
var anonymous = new Person();
Console.WriteLine($"Hello, {anonymous.Name}!");
// > Hello, Anonymous user!
// 2. Person with assigned value
var me = new Person { Name = "#codez0mb1e"};
Console.WriteLine($"Hello, {me.Name}!");
// > Hello, #codez0mb1e!
// 3. Attempt to re-assignment Name
me.Name = "My fake";
// > Compilation error: Init-only property can only be assigned in an object initializer
In addition to the answer already accepted, for the scenario when you want to define a default property as a function of other properties you can use expression body notation on C#6.0 (and higher) for even more elegant and concise constructs like:
public class Person{
public string FullName => $"{First} {Last}"; // expression body notation
public string First { get; set; } = "First";
public string Last { get; set; } = "Last";
}
You can use the above in the following fashion
var p = new Person();
p.FullName; // First Last
p.First = "Jon";
p.Last = "Snow";
p.FullName; // Jon Snow
In order to be able to use the above "=>" notation, the property must be read only, and you do not use the get accessor keyword.
Details on MSDN
In C# 6 and above you can simply use the syntax:
public object Foo { get; set; } = bar;
Note that to have a readonly property simply omit the set, as so:
public object Foo { get; } = bar;
You can also assign readonly auto-properties from the constructor.
Prior to this I responded as below.
I'd avoid adding a default to the constructor; leave that for dynamic assignments and avoid having two points at which the variable is assigned (i.e. the type default and in the constructor). Typically I'd simply write a normal property in such cases.
One other option is to do what ASP.Net does and define defaults via an attribute:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
My solution is to use a custom attribute that provides default value property initialization by constant or using property type initializer.
[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];
}
}
To use this attribute it's necessary to inherit a class from special base class-initializer or use a static helper method:
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);
}
}
}
Usage example:
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);
}
Output:
Item1
(X=3,Y=4)
StringValue
little complete sample:
using System.ComponentModel;
private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
get { return bShowGroup; }
set { bShowGroup = value; }
}
You can simple put like this
public sealed class Employee
{
public int Id { get; set; } = 101;
}
In the constructor. The constructor's purpose is to initialized it's data members.
private string name;
public string Name
{
get
{
if(name == null)
{
name = "Default Name";
}
return name;
}
set
{
name = value;
}
}
Have you tried using the DefaultValueAttribute or ShouldSerialize and Reset methods in conjunction with the constructor? I feel like one of these two methods is necessary if you're making a class that might show up on the designer surface or in a property grid.
Use the constructor because "When the constructor is finished, Construction should be finished". properties are like states your classes hold, if you had to initialize a default state, you would do that in your constructor.
To clarify, yes, you need to set default values in the constructor for class derived objects. You will need to ensure the constructor exists with the proper access modifier for construction where used. If the object is not instantiated, e.g. it has no constructor (e.g. static methods) then the default value can be set by the field. The reasoning here is that the object itself will be created only once and you do not instantiate it.
#Darren Kopp - good answer, clean, and correct. And to reiterate, you CAN write constructors for Abstract methods. You just need to access them from the base class when writing the constructor:
Constructor at Base Class:
public BaseClassAbstract()
{
this.PropertyName = "Default Name";
}
Constructor at Derived / Concrete / Sub-Class:
public SubClass() : base() { }
The point here is that the instance variable drawn from the base class may bury your base field name. Setting the current instantiated object value using "this." will allow you to correctly form your object with respect to the current instance and required permission levels (access modifiers) where you are instantiating it.
public Class ClassName{
public int PropName{get;set;}
public ClassName{
PropName=0; //Default Value
}
}
This is old now, and my position has changed. I'm leaving the original answer for posterity only.
Personally, I don't see the point of making it a property at all if you're not going to do anything at all beyond the auto-property. Just leave it as a field. The encapsulation benefit for these item are just red herrings, because there's nothing behind them to encapsulate. If you ever need to change the underlying implementation you're still free to refactor them as properties without breaking any dependent code.
Hmm... maybe this will be the subject of it's own question later
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; }
}
I know this is an old question, but it came up when I was looking for how to have a default value that gets inherited with the option to override, I came up with
//base class
public class Car
{
public virtual string FuelUnits
{
get { return "gasoline in gallons"; }
protected set { }
}
}
//derived
public class Tesla : Car
{
public override string FuelUnits => "ampere hour";
}
I think this would do it for ya givng SomeFlag a default of false.
private bool _SomeFlagSet = false;
public bool SomeFlag
{
get
{
if (!_SomeFlagSet)
SomeFlag = false;
return SomeFlag;
}
set
{
if (!_SomeFlagSet)
_SomeFlagSet = true;
SomeFlag = value;
}
}
I have a Vote class and one of the properties it can have is a vote type. Such as unanimous, a 3/4 vote, a simply majority, etc. Each type needs to have a string associated with it which will describe the vote type (like "A simply majority requires 51% to pass" etc.). I need to pass these vote types/description in with my view model to my view and then I can make my drop down list with it.
Then, when the form that creates the vote is submitted I just need to bind the vote type (without description) to the Vote model (which is part of the view model).
I've only been using C# for a short time and I don't quite understand how the enums work in it. Perhaps enum is not the way to go about this.
public class VoteViewModel
{
public VoteViewModel()
{
Vote = new Vote();
}
public Vote Vote { get; set; }
public int EligibleVoters { get; set; }
}
And this is where I'll be putting the drop down.
<section class="vote-type">
<select name="">
<option value="">Select Vote Type</option>
</select>
<section class="vote-type-info">
<p class="vote-rules">To pass this vote, at least 51% of Eligible Voters must vote to approve it.</p>
</section>
</section>
Please notice I'm only showing for strings for it could be any type. In each case I mention how to extend it for more values if possible.
Using the enum as a key
You can use your enum type as a key for a dictionary (you want to be unique, so make it static and readonly in some helper class):
private static readonly Dictionary<MyEnum, string> _dict =
{
//Using dictionary initialization
{MyEnum.MyValue, "The text for MyValue"},
{MyEnum.MyOtherValue, "Some other text"},
{MyEnum.YetAnotherValue, "Something else"}
}
public static readonly Dictionary<MyEnum, string> Dict
{
get
{
return _dict;
}
}
And access the associated value:
string text = Dict[MyEnum.MyValue];
Or with:
string text;
if (Dict.TryGetValue(MyEnum.MyValue, out text))
{
//It has the value
}
else
{
//It doesn't have the value
}
This way you can access a string that is associated with the enum value. Then you can expose your Dictionary so that you can read the corresponding values.
You will need a complex type for storing more than one value. Just use your custom type isntead of string. Or if available you can use Tuples.
Accesing the Dictionary may mean an extra annoyance and hopefully it will not mean a threading problem too.
Enum.GetName
You can use Enum.GetName to read the name of the values of your enum:
string text = Enum.GetName(MyEnum.MyValue);
//text will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text = Enum.GetName(some);
Note: ToString() should work too.
Sadly, this will not work for something else than the string.
Also it has the drawback that you cannot put any text there (it has to be a valid identifier).
Custom Attributes
You will have to declare an attribute type:
[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : System.Attribute
{
public readonly string _value;
public string Value
{
get
{
return _value;
}
}
public EnumValueAttribute(string value) // value is a positional parameter
{
//beware: value can be null...
// ...but we don't want to throw exceptions here
_value = value;
}
}
Now you apply the attribute to your enum:
public enum MyEnum
{
[EnumValue("The text for MyValue")]
MyValue = 1,
[EnumValue("Some other text")]
MyOtherValue = 2,
[EnumValue("Something else")]
YetAnotherValue = 3
}
Lastly you will need to read the attribute back:
public static string GetValue(MyEnum enumValue)
{
FieldInfo fieldInfo = typeof(MyEnum).GetField(enumValue.ToString());
if (!ReferenceEquals(fieldInfo, null))
{
object[] attributes = fieldInfo.GetCustomAttributes(typeof(EnumValueAttribute), true);
if (!ReferenceEquals(attributes, null) && attributes.Length > 0)
{
return ((EnumValueAttribute)attributes[0]).Value;
}
}
//Not valid value or it didn't have the attribute
return null;
}
Now you can call it:
string text1 = GetValue(MyEnum.MyValue);
//text1 will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text2 = GetValue(some);
You can add more fields to your attribute class and use them to pass any other value you may need.
But this requires reflexion, and it may not be available if you are running in a sandbox. Also it will retrieve the attributes each time, creating some short lived objects in the proccess.
Emulate Enum
You can emulate an enum with a sealed class that has no public constructor and exposes static readonly instances of itself:
public sealed class MyEnumEmu
{
private static readonly string myValue = new MyEnumEmu("The text for MyValue");
private static readonly string myOtherValue = new MyEnumEmu("Some other text");
private static readonly string yetAnotherValue = new MyEnumEmu("Something else");
public static MyEnumEmu MyValue
{
get
{
return myValue;
}
}
public static MyEnumEmu MyOtherValue
{
get
{
return myOtherValue;
}
}
public static MyEnumEmu YetAnotherValue
{
get
{
return yetAnotherValue;
}
}
private string _value;
private MyEnumEmu(string value)
{
//Really, we are in control of the callers of this constructor...
//... but, just for good measure:
if (value == null)
{
throw new ArgumentNullException("value");
}
else
{
_value = value;
}
}
public string Value
{
get
{
return _value;
}
}
}
Use it as always:
var some = MyEnumEmu.MyValue;
And access the associated value:
string text = MyEnumEmu.MyValue.Value;
//text will have the text "MyValue"
//or
string text = some.Value;
This is the more flexible of all, you can either use a complex type instead of string or add extra fields for passing more than a single value.
But... it is not really an enum.
You could create a "constant" dictionary (or rather readonly static, since you can't create a constant dictionary) around your Enum.
public enum VoteType { Unanimous = 1, SimpleMajority = 2, ... }
public static readonly Dictionary<VoteType, string> VoteDescriptions = new Dictionary<VoteType, string>
{
{ VoteType.Unanimous, "Unanimous description" },
{ VoteType.SimpleMajority, "Simple majority" },
...
};
public class Vote()
{
public VoteType VoteSelectType { get; set; }
}
public enum VoteType
{
[Display(Name = "Enter Text Here")]
unanimous = 1,
[Display(Name = "Enter Text Here")]
threequatervote = 2,
[Display(Name = "Enter Text Here")]
simplymajority = 3
}
Goto here this is pretty much your solution
How do I populate a dropdownlist with enum values?
You can use enums if you want but you need to decide how to make the link between the enum value and what you want to display. For example, an enum value of SimpleMajority you would want displayed as "Simple Majority". One way to do this is using the Description attribute and a helper class as described here.
However, you might find it easier to set up a lightweight collection class to store vote type values and their description. This could be as simple as a Dictionary<int, string> You will probably find this a more straightforward approach.
Since you have the type and description I'll better suggest you to create a class that wraps up both instead of enum. The advantage is you can reduce more work and it's very flexible.
public class VoteType
{
public string Name{ get; set; }
public string Description{ get; set; }
}
Now your Vote class will have reference to this VoteType.
public class Vote
{
...
public VoteType Type{ get; set; }
}
In your VoteViewModel you better have a class that contains all the VoteTypes.
public class VoteViewModel
{
...
public IEnumerable<SelectListItem> VoteTypes{ get; set; }
}
Now you can easily bind the VoteTypes in a dropdownlist.
#model VoteViewModel
#Html.DropDiwnListFor(m => m.VoteTypes,...)
I have used this before, it is really handy.
http://www.codeproject.com/Articles/13821/Adding-Descriptions-to-your-Enumerations
In short what it lets you do is:
public enum MyColors{
[Description("The Color of my skin")]
White,
[Description("Bulls like this color")]
Red,
[Description("The color of slime")]
Green
}
and then get the description back by simply calling:
String desc = GetDescription(MyColor.Green);
It does use reflection though, so there is a tradeoff between simplicity and a slight performance hit. Most of the time I'd take the performance hit...
I'm trying to build a class which will initalise its self either by passing in a reference to a record in a database (with the intention that a query will be run against the database and the returned values for the objects properties will be set therein), or by specifying the values "by hand" - this no database call is required.
I've looked at a couple textbooks to discover the "Best-practice" for this functionality and sadly I've come up short.
I've written a couple sample console apps reflecting what I believe to be the two most probable solutions, but I've no Idea which is the best to implement properly?
Sample App #1 uses what most books tell me is the "preferred" way but most examples given alongside those claims do not really fit the context of my situation. I'm worried in here that the flow is not as readable as App #2.
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester() : this(0) { }
public OverloadedClassTester (int _ID) : this (_ID, "", 0)
{
this.age = 14; // Pretend that this was sourced from a database
this.Name = "Steve"; // Pretend that this was sourced from a database
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
This Sample (App #2) "appears" more readable - in that I think it's easier to see the flow of operation. However it does appear efficient in terms of characters saved :p. Also, is it not dangerous that it calls a method of the object before it's fully initialised, or is this not a concern?
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester()
{
initialise(0, "", 21); // use defaults.
}
public OverloadedClassTester (int _ID)
{
var age = 14; // Pretend that this was sourced from a database (from _ID)
var Name = "Steve"; // Pretend that this was sourced from a database (from _ID)
initialise(_ID, Name, age);
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
initialise(_ID, _Name, _age);
}
public void initialise(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
What is the "correct" way to solve this problem, and why?
Thanks,
I would definitely chain the constructors, so that only one of them does the "real work". That means you only have to do the real work in one place, so if that work changes (e.g. you need to call some validation method at the end of the constructor) you only have one place where you need to change the code.
Making "simple" overloads call overloads with more parameters is a pretty common pattern IME. I find it more readable than the second version, because you can easily tell that calling one overload is going to be the same as calling the "bigger" one using the default values. With the second version, you have to compare the bodies of the constructors.
I try not to have more than one constructor which chains directly to the base class wherever possible - unless it's chaining to a different base class constructor, of course (as is typical with exceptions).
Do not use database calls in a constructor. This means your constructor is doing a lot of work. See http://misko.hevery.com/code-reviewers-guide/ (Google guide for writing testable code).
Apart from this, chaining constructors (option 2) looks good. Mostly because as you say it is readable. But why are you assigning this.Name etc in the constructor and doing it again in initialize. You could assign all values in initialize.
Maybe something like this?
public class OverloadedClassTester
{
public int Id { get; private set; }
public string Name { get; private set; }
public int Age { get; private set; }
public OverloadedClassTester (Person person)
: this (person.Id, person.Name, person.Age) { }
public OverloadedClassTester(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
public override string ToString()
{
return String.Format("Id: {0}\nName: {1}\nAge: {2}\n\n",
Id, Name, Age);
}
}
maybe it would be better to use optional parameters? In this case, you would create a single constructor and initialize the values to the parameters you wish to set.
More information: link text
I prefer #1, the chaining constructors, from a maintenance perspective. When someone comes back to edit the code later on, you wouldn't want them to edit the initialise() method and not realize that it is being called from a constructor. I think it is more intuitive to have all the functional parts in a constructor of some kind.
Personally, I use constructor chaining like that all the time.
Not sure if I worded this correctly ... but I have the following code:
public Guid ItemId
{
get;
}
public TransactionItem()
{
this.ItemId = Guid.Empty;
}
Naturally I am getting a read-only issue ... which I do understand. Is there anyway to set this property value without having to do something like the below:
Guid _itemId = Guid.Empty;
public Guid ItemId
{
get
{
return _itemId;
}
set
{
_itemId = value;
}
}
or
public Guid ItemId
{
get;
internal set;
}
Thanks in advance!
I would go for this:
public Guid ItemId
{
get;
private set; // can omit as of C# 6
}
public TransactionItem()
{
this.ItemId = Guid.Empty;
}
Of course, it would be open for setting within this class, but since you are writing it I hope you have the sense to not break your own intentions...
In my opinion, things like readonly properties, are mostly important when seen from the outside. From the inside, it doesn't really matter what it is, cause there, you are the King =)
If you just need the ItemId property to be read-only for external users of your class, then Svish's answer is the way to go.
If you need ItemId to be read-only within the class itself then you'll need to do something like this:
private readonly Guid _ItemId
public Guid ItemId
{
get { return _ItemId; }
}
public TransactionItem()
{
_ItemId = Guid.Empty;
}
You can use readonly keyword
public readonly Guid ItemId;
public TransactionItem()
{
this.ItemId = Guid.Empty;
}
I'm afraid your question isn't very clear - but if there isn't a property setter defined, then you certainly can't call it.
Are you actually after an automatically implemented read-only property, allowing setting just within the constructor? If so, I'm afraid that's not available, much as I'd like it.
Just to expand on what I mean, I'd like to be able to do:
// Not valid in C# - yet!
public class Foo
{
// Autogenerated field would be readonly in IL.
public string Name { get; readonly set; }
public Foo (string name)
{
this.Name = name;
}
public void Bar()
{
// This would be invalid
this.Name = "No!";
}
}
Basically it would be "make a property like a readonly field."
Use a private setter, or set the backing field ?
(But, then you must make sure that the name of your backing field can be determined based on the property-name.
For instance by making sure that your backing field always has the same name as the property-name, but is prefixed with an underscore; like NHibernate does it using its access-strategies).