I was unable to define what to name this problem, thus tried google and here, but cant find.
Is there any way to set array(or dictionary) members value on property level, and set attribute onto them? like this:
public class XYZ{
private string[] x= new string[]{"smth", "smth"};
x[0] { get; set; }
[Receipt(order=2, name="warranty")]
x[1] { get; set; }
....
}
So, mainly I have to questions to be frank:
1) Is that possible to set attributes onto array members?
2) Is that possible (forget attribute) to assign value to array member in property level (not within method), like this?:
public class XYZ{
private string[] x= new string[2]();
x[0] = "smth";
}
The answer is definitely no. Attributes can only be added onto compile-time features such as classes and methods. Not onto runtime features such as object data.
Also your getter/setter syntax is very wrong, it can only be like this:
public int Month { get; set; }
So an access modifier (public; optional), followed by a Type (int), followed by the name (Month), and then the get and/or set specification.
You can't do it exactly the way you want, but you can get close:
public class XYZ
{
private string[] x= new string[]{"smth", "smth"};
[Receipt(order=1, name="warranty")]
public string Receipt1 {get { return x[0];} set{x[0] = value;} }
[Receipt(order=2, name="warranty")]
public string Receipt2 {get { return x[1];} set{x[1] = value;} }
//...
}
Of course, the number of entries here are fixed, and you have to give these properties a real, meaningful name. You can't have a dynamic number of entries that changes while the program runs.
The one other thing you can look at is an indexer property. With an indexer, you can only set your attribute once on the whole property, rather than individual elements, but it will allow the number of items to change at run time.
The short answer is no. Attributes are for metadata, and this looks like actual data. Probably you should have your array be an array of some class that contains the value (i.e. smth) and all the data you wanted to have in your ReceiptAttribute.
So something like:
public class Receipt
{
public string Value {get; set;}
public int Order {get; set;}
public string Name {get; set;}
}
And then:
public class XYZ
{
private Receipt[] x= new Receipt[]
{
new Receipt() { Value = "smth", Order = 1, Name = "warranty" },
new Receipt() { Value = "smth", Order = 2, Name = "warranty" },
};
}
And, obviously, when you want the value you'd do something like:
x[0].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;
}
}
Foreword: this is a long question and if you don't want to read and understand why I'm asking it then please spare the comment "why not simply test the code?"
I have an object model that looks somewhat like this:
public class MyObjectModel
{
public byte TypeOfNestedObject { get; set; }
public string NestedObjectInJson { get; set; }
public NestedObjectModel1 { get; set; }
public NestedObjectModel2 { get; set; }
public NestedObjectModel3 { get; set; }
public MyObjectModel()
{
NestedObjectModel1 = null;
NestedObjectModel2 = null;
NestedObjectModel3 = null;
}
public void DeserializeJsonString()
{
if (TypeOfNestedObject == 1) {
NestedObjectModel1 = "deserialize NestedObjectInJson
into NestedObjectModel1";
}
if (TypeOfNestedObject == 2) {
NestedObjectModel2 = "deserialize NestedObjectInJson
into NestedObjectModel2";
}
if (TypeOfNestedObject == 3) { NestedObjectModel3 ... }
}
}
Basically, the object is composed of three nested objects (NestedObjectModel1, NestedObjectModel2 and NestedObjectModel3). However, only one of them is actually used at any given time. In the database, I store fields that are used to recreate this object and one of the database fields is a json string that contains one of the three nested objects for a particular instance.
My query looks somewhat like this:
var TheObjectModel = from t in MyDC.Table
.....
select new MyObjectModel()
{
TypeOfNestedObject = t.TypeOfNestedObject,
NestedObjectInJson = t.NestedObjectInJson
};
I use the property TypeOfNestedObject to know which nested object the particular instance of MyObjectModel has. For the moment, after the the query has executed, I run a method that reads TypeOfNestedObject and deserializes the string NestedObjectInJson to the appropriate type and adds the deserialized object as the corresponding nested object.
Now I want to add a custom setter to NestedObjectInJson so that when this property is set when the query runs, the object automatically deserializes the string to the appropriate type. However, for this to work, the object would also have to have the property TypeOfNestedObject properly set. I want to write the setter like this:
public NestedObjectInJson
{
set {
if (this.TypeOfNestedObject == 1) {
NestedObjectModel1 = "deserialize NestedObjectInJson
into NestedObjectModel1 ";
}
}
}
If I write the setter like this, is the property TypeOfNestedObject needs to be available at the time the setter runs. If you notice, in the query, I load TypeOfNestedObject before I load NestedObjectInJson.
So the question is this: If I decide to remove the call to DeserializeJsonString and create this custom setter, will the property TypeOfNestedObject be available because in the query it's set before NestedObjectInJson or is the order in which the query is written make the availability of the property TypeOfNestedObject unpredictable?
This would work, the order is predictable.
However, I would advise against something like that. The clean approach would be to provide a constructor that takes the type and the JSON and performs the deserialization.
With that approach you would avoid the temporal coupling you currently have.
I have the next object (Tree structured Object):
public class someClass
{
ObservableCollection<someClass> Children { get; }
long NumOfSelectedChildren { get; set; }
}
//There is more properties but its not important for my question
I need to scan a given "someClass" Object and set for every node into the property NumOfSelectedChildrenthe number Of his children.
I wrote some recursion that do this task but I must send the NumOfSelectedChildren proprty as reference. Currently, when my recursion finished all the "NumOfSelectedChildren" properties are equal to 0 because the recursion move the parameters by value and not by reference.
When I`m trying to send the property as "ref" I get the following error:
"Error 23 A property, indexer or dynamic member access may not be passed as an out or ref parameter"
How can I make sure that this property will be sent by reference and not by value?
Thanks.
You haven't shown how you update the NumOfSelectedChildren property, so let me propose an alternate solution that doesn't require you to pass a property by reference:
public class someClass
{
ObservableCollection<someClass> Children { get; }
long NumOfSelectedChildren { get; set; }
int UpdateNumOfSelectedChildren()
{
return NumOfSelectedChildren =
Children.Sum(x => 1 + x.UpdateNumOfSelectedChildren());
}
}
In my code, I have a class that maintains a number of lists. We'll focus on one of them for the moment, since it's the one that highlighted the problem.
internal List<Badge> Badges { get; private set; }
In the code, I add Badge instances to this list when an XML document is parsed. Later, I want to update the individual instances in the list so I can have the data written back out to XML. Because of the way the data's XML structure differs from the original file structure, there's some hocus-pocus involved, but that's largely mapped out. The surprise came when I attempted to update an item in the List<Badge>.
Specifically, the problematic code is here:
// Get the current badge from the loaded XML data, so we can update it.
var currentBadge = this.GameData.GetCurrentBadge();
I always get a valid badge back. The surprise, as I've come to find out, is that this simple test always fails:
var result = this.GameData.Badges.IndexOf(currentBadge);
result always evaluates to -1, indicating that the object doesn't exist in the collection. (EDIT: Updating the properties on currentBadge has no effect whatsoever on the contents of the matching item in this.GameData.Badges.) Which leads me to conclude that I'm getting a copy of my object back, and not a reference, as I would have expected.
For the inquisitive, the code to retrieve badges from the GameData class is included below. I have a sneaking suspicion that this is a documented behavior of generic lists, and that this is the first time I've stumbled across it. If so, I'm in for a very rude awakening. If it's not, I'd really like to know why my objects are coming back "disconnected" from their originals.
private Badge GetCurrentBadge()
{
var badgeItem = GetCurrentBadgeItem();
if (badgeItem != null)
{
return this.GameData.GetBadgeByText(badgeItem.Text);
}
return null;
}
private MenuOption GetCurrentBadgeItem()
{
if (!(this.currentItem is MenuOption &&
(this.currentItem as MenuOption).IsLocked))
{
return null;
}
MenuOption result = null;
var children = this.currentMenu.Children;
for (var n = children.Count - 1; n >= 0; n--)
{
var child = children[n] as MenuOption;
if (child == null || !child.IsLocked)
{
break;
}
if (!child.Text.StartsWith(" "))
{
result = child;
break;
}
}
return result;
}
UPDATE: Per request, GetBadgeByText, which comes from the GameData class.
internal Badge GetBadgeByText(string badgeText)
{
foreach (var badge in Badges)
{
if (badge.Text.ToLower() == badgeText.ToLower())
{
return badge;
}
}
return null;
// var b = (from l in Badges
// where l.Text.ToLower().StartsWith(badgeText.ToLower())
// select l).FirstOrDefault();
//return b;
}
As you can see, I've tried it both with and without Linq, just to eliminate that as the culprit. Changing the implementation had no noticable effect.
And for the record, all the objects in this application are CLASSES. No structs anywhere.
UPDATE #2: The Badge class.
internal class Badge
: GameDataItem
{
public Badge()
: base()
{
}
public string AuthId { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public bool IsAccoladePower { get; set; }
public string RequiredBadges { get; set; }
public override string ToString()
{
return Text;
}
internal string ToXml()
{
var template = "<Badge value=\"{0}\" title=\"{1}\" category=\"{2}\" authid=\"{3}\" requires=\"{4}\" accolade=\"{5}\" description=\"{6}\" />";
return string.Format(template,
this.Value,
this.Text,
this.Category,
this.AuthId,
this.RequiredBadges,
this.IsAccoladePower,
this.Description);
}
}
And just in case someone asks for it, the base class:
internal class GameDataItem
{
private string _text;
public string Text
{
get
{
return this._text;
}
set
{
this._text = value.Replace("<", "<")
.Replace(">", ">")
.Replace("&", "&");
}
}
public string Value { get; set; }
public override string ToString()
{
return Text + "=\"" + Value + "\"";
}
}
Looks to me like this has something to do with MenuOption's implementation of Equals(object). The IndexOf() method of the List<> will use Equals(object) when deciding what to return.
Either:
You are putting a copy of the object in the list. (List<T> does not clone objects or do any other sort of trickery.)
Badge is a struct, not a class, which means that you don't actually hold references to it since it would be a value type.
There's some copying going on elsewhere in code you haven't pasted.
A generic List<T> does not copy objects. You add references to it, and the same references comes out - so there must be another problem in the code.
How is GetBadgeFromText implemented ? Does it read directly from the Badges List ?
Is this a web app ? If yes, does your List live between requests, or is it deserialized and serialized on each request (this could also be the problem).