What's the difference between:
public List<MyType> Something{ get; set; } = new List<MyType>();
and
public List<MyType> Something{
get{
return new List<MyType>();
}
//set...
}
Context:
I'm unsure of the behaviour I'm seeing in my code. A service is there on constructor, but null on a future method call in the what I assume is the same instance of the class.
The first line:
public List<MyType> Something{ get; set; } = new List<MyType>();
will be called once when the object (that has this property) is instantiated. It is a one time creation of an instance of Something.
The second example is an explicit implementation of the getter. Every time you access the getter of Something it will return a new and empty list.
EDIT:
The first line is called an auto-property initializer for a detailed answer have a look at a post by Jon Skeet. This feature exists since C# 6.0
Related
What exactly does it mean when assigning new() to a property?
I found some examples of seeing new usage in method calls but not like the below.
public ObservableCollection<Customer> Customers { get; } = new();
It's target-typed new, essentially it will create an object of whatever the left of the operand is.
In the case of auto-properties, it will assign a new instance of the type of that property, to the property.
So if we strip away all of the syntactic sugar, what you've essentially got is:
private ObservableCollection<Customer> _customers = new ObservableCollection<Customer>();
public ObservableCollection<Customer> Customers
{
get
{
return _customers;
}
}
Incidentally, you can use a target-typed new almost anywhere there's a well-known type, not just on auto-properties.
This is a target-typed new expression (introduced in C# 9) and is equivalent to:
public ObservableCollection<Customer> Customers { get; } = new ObservableCollection<Customer>();
So the Customers is an auto implemented property which initialized to a newly created instance of ObservableCollection<Customer>.
Recently, I came across some code that looked like this:
public class Test
{
public ICollection<string> Things { get; set; }
public Test()
{
Things = new List<string> { "First" };
}
public static Test Factory()
{
return new Test
{
Things = { "Second" }
};
}
}
Calling Test.Factory() results in a Test object with a Things collection containing both "First" and "Second".
It looks like the line Things = { "Second" } calls the Add method of Things. If the ICollection is changed to an IEnumerable, there is a syntax error stating "IEnumerable<string> does not contain a definition for 'Add'".
It is also apparent that you can only use this kind of syntax in an object initialiser. Code such as this is invalid:
var test = new Test();
test.Things = { "Test" };
What is the name of this feature? In which version of C# was it introduced? Why is it only available in object initialisers?
It is called a collection initializer and it was added in the C# 3 language specifications (section 7.5.10.3 at introduction, section 7.6.10.3 in the current specs). To be specific, the code you use uses an embedded collection initializer.
Collection initializer actually just call the Add method, which is required according to the specs.
As Quantic commented, the specs say:
A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Instead of assigning a new collection to the field or property, the elements given in the initializer are added to the collection referenced by the field or property.
That explains your unexpected results quite good.
Why is it only available in object initialisers?
Because it doesn't make sense elsewhere. You could just call the Add method yourself instead of using initializers for something else than initializing.
As Patrick already mentioned the collection initializer sequentially calls Add on the list. This assumes your property has been initialized by a constructor accordingly:
public class MyClass
{
public List<MyType> TheList { get; private set; }
public MyClass()
{
this.TheList = new List<MyType>();
}
}
If there is no such constructor that initializes your list you'll get a NullReferenceException in the following statement:
test.Things = { "Test" };
However this is something different than the following:
var m = new MyClass { TheList = new List<MyType> { ... } };
in which case you'll access the properties setter. Having none (or only a private one as in my example) leads to a compiler-error.
I'm trying to understand how the line:
private Queue<IProductable> inventory { get; set; }
It is used in the entire code below. I'm only used to seeing properties defined using simple types; so, this really confused me. Also, I'm curious why the constructor for the class Factory (below) uses:
inventory = new Queue<IProductable>();
Instead of:
Queue<IProductable> inventory = new Queue<IProductable>();
My understanding is when you instantiate an new object, you should do: CLASS/TYPE newObjectName = new CLASS/TYPE. Is the constructor even instantiating a new "inventory" object? If so, why don't I have to specify what type the object "inventory" is (in order to use it to invoke methods from the generic Collections class, Queue).
Anyway, below, is the code. I'm hoping someone can explain this in the easiest possible way for me to comprehend/remember when I need to do something similar in the future.
namespace codeExample
{
class Factory
{
private Queue<IProductable> inventory { get; set; }
public Factory()
{
inventory = new Queue<IProductable>();
}
public IProductable GetOldestItem()
{
IProductable oldestItem = inventory.First();
return oldestItem;
}
public IProductable GetNewestItem()
{
IProductable newestItem = inventory.Last();
return newestItem;
}
public void Add(IProductable productToAdd)
{
inventory.Enqueue(productToAdd);
}
}
}
My understanding is when you instantiate an new object, you should do: CLASS/TYPE newObjectName = new CLASS/TYPE. Is the constructor even instantiating a new "inventory" object?
If the type were included then it would be creating a new local variable. Currently the code is not creating a new variable, it is using the property instead, which is a part of that class's instance data (at least in this case). The property (in this specific context) acts almost exactly like a private field would. It is creating a variable that exists for the lifetime of the whole object, not just one method.
Is the constructor even instantiating a new "inventory" object?
It's creating a new queue object, yes. The property definition defines where a queue may be stored, but it doesn't create an actual queue. The constructor actually creates a queue (which is empty) and assigns is to the variable.
The private Queue<IProductable> inventory { get; set; } declares an auto-implemented property, but it could as well have been a field:
private Queue<IProductable> inventory;
This declares a private instance variable, which you can access from any method in this class, but not from derived classes or from outside the class.
Your code assigns a value in the constructor, which is always run before other code in the class:
inventory = new Queue<IProductable>();
So now from everywhere in this class you can access inventory.
I'm only used to seeing properties defined with simple types; so, this
really confused me
Why? You can define properties of any type.
Also, I'm curious why the constructor for the class Factory (below)
uses:
You can't define the type of the property again, it's already available in the current scope because it's a class property. Its type is defined at the line private Queue<IProductable> inventory { get; set; }
My understanding is when you instantiate an new object, you should do:
CLASS/TYPE newObjectName = new CLASS/TYPE
No, here is a simple counter-example in two lines:
MyType myVariable;
...
myVariable = new MyType();
private Queue<IProductable> inventory { get; set; }
is an auto property.
it's equivalent to
private Queue<IProductable> _inventory;
public Queue<IProductable> Inventory
{
get { return _inventory; }
set { _inventory = value; }
}
Thus, you just declared a member inventory, and later on you instantiate a Queue<IProductable> and store its reference to the auto property inventory.
inventory = new Queue<IProductable>();
private Queue<IProductable> inventory { get; set; } is an automatic property. The implementation of get/set are provided by the compiler.
vs
Queue<IProductable> inventory = new Queue<IProductable>();
Now, inventory is a field. Properties have backing stores and are smarter than fields. They allow a programmer to do work during get/set operations.
Is the constructor even instantiating a new "inventory" object?
Yes, in the example the constructor is setting the hidden variable (backing store).
If so, why don't I have to specify what type the object "inventory" is
(in order to use it to invoke methods from the generic Collections
class, Queue).
Because you are not declaring a new variable in the constructor. We are setting a property.
Here you could use a field instead of a property. However, I would expect an "advanced class"/Factory to use Dependency Injection and thus a public property would make sense in such a case. (Maybe you simplified the original code?)
Why are we able to write
public int RetInt
{
get;set;
}
instead of
public int RetInt
{
get{return someInt;}set{someInt=value;}
}
What is the difference between the two?
This feature is called Auto implemented properties and introduced with C# 3.0
In C# 3.0 and later, auto-implemented properties make
property-declaration more concise when no additional logic is required
in the property accessors. They also enable client code to create
objects. When you declare a property as shown in the following
example, the compiler creates a private, anonymous backing field
that can only be accessed through the property's get and set
accessors.
class Customer
{
// Auto-Impl Properties for trivial get and set
public double TotalPurchases { get; set; }
public string Name { get; set; }
public int CustomerID { get; set; }
For your question
What is the difference between the two?
In your case, none. Since you are not doing anything while setting or retrieving the value, but suppose you have want to do some validation or want to perform other types of check then :
private int someInt;
public int RetInt
{
get
{
if (someInt > 0)
return someInt;
else
return -1;
}
set { someInt = value; } // same kind of check /validation can be done here
}
The above can't be done with Auto implemented properties.
One other thing where you can see the difference is when initializing a custom class type property.
If you have list of MyClass
Then in case of Normal property, its backing field can be initialized/instantiated other than the constructor.
private List<MyClass> list = new List<MyClass>();
public List<MyClass> List
{
get { return list; }
set { list = value; }
}
In case of Auto implemented property,
public List<MyClass> SomeOtherList { get; set; }
You can only initialize SomeOtherList in constructor, you can't do that at Field level.
How are these two different ?
There are different at least by 2 points:
In normal property you have to define a field before (someInt in your case)
In normal property you can set a breakpoint into the set/get modifiers, instead in auto property can not do that.
In other words: if you need "just property", use auto-properties, if you need more control over workflow (raise an event on set, debug, run other stuff inside), use "normal" properties.
These are auto implemented properties. Please see http://msdn.microsoft.com/en-us/library/bb384054.aspx for more info.
Basic reason why these were introduced was to reduce the overhead of programmer of creating a private variable like someInt which had little use than being used in a property.
Actually these aren't really different, in both cases you have a private field that corresponds to your property, but in the first case it is generated by the compiler and hidden.
If you need to use the variable behind the property quite often in your class, I think it's better to declare your property the old way (2nd one), because each time you will access it this will call the getter if you do it the "new" way.
If you only need it to be used from outside your class (or in most of cases), then you can go with the "new" way (1st one)
Consider the class:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
According to MSDN:
Properties are members that provide a flexible mechanism to read,
write, or compute the values of private fields. Properties can be used
as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily
And:
Properties enable a class to expose a public way of getting and
setting values, while hiding implementation or verification code.
A get property accessor is used to return the property value, and a
set accessor is used to assign a new value. These accessors can have
different access levels. For more information, see Accessor
Accessibility.
The value keyword is used to define the value being assigned by the
set indexer.
Properties that do not implement a set method are read only.
while still providing the safety and flexibility of methods.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
edit removed readonly from property
edit2 also would like to clarify that this is not the best use for a property but its done to try and illustrate the question more effectively.
You return a new object on each access to the property and that is not the expected behavior of properties. Instead you should return the same value each time (e.g. a value stored in a field). A property getter is simply glorified syntax for a method that returns a value. Your code compiles into something like this (the compiler creates a getter by prefixing the property name with get_ which is then emitted as IL):
public class foo
{
public object get_newObject()
{
return new object();
}
}
Each call to the getter will create a new object that foo doesn't know about or has access to.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
No.
Property using a backing field:
class Foo {
readonly Object bar = new Object();
public Object Bar { get { return this.bar; } }
}
Using automatic properties:
class Foo {
public Foo() {
Bar = new Object();
}
public Object Bar { get; private set; }
}
A property is accessed using the same easy syntax as a public field. However, by using a property you can add code to the getter and the setter allowing you to do stuff like lazy loading in the getter or validation in the setter (and much more).
Under the hood, your property will simply be calling a function named get_newObject() that looks like this:
public object get_newObject()
{
return new object();
}
Since that is the case, it will always return a new object every time it is invoked.
If you want to retain a reference to the object, then I would recommend creating a private field to hold the data and having the property access that field, like so:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
Since your property doesn't define set, and your field is private, newObject is basically eradonly outside of the containing class.
Properties in C# are "syntactic sugar". The code within the get block of a property is in fact put into a hidden get_PropertyName() method, and the set block into a hidden set_PropertyName() method. In the case of your code, the following method will be created:
public object get_newObject()
{
return new object();
}
You can see these hidden methods if you view the compiled assembly using Reflector, or ildasm.
When the property is used, the C# compiler converts any "get" accesses of your property into calls of the get_newObject() method. As an example:
If you were to write the following:
var foo = new foo();
var aNewObject = foo.newObject;
The compiler would convert that to:
var foo = new foo();
var aNewObject = foo.get_newObject();
So, in answer to your other question, the newly created object returned when someone "gets" the property won't be stored within your foo instance, the caller will simply get a new object every time.
Not exactly. Properties are just syntactic sugar so that you don't have to write accessor methods (like Java).
So this:
private int _myInteger;
public int MyInteger
{
get { return _myInteger; }
set { _myInteger = value; }
}
is equivilant to this:
private int _myInteger;
public int GetMyInteger()
{
return _myInteger;
}
public void SetMyInteger(int value)
{
_myInteger = value;
}
and it gets better with this, which is also equivilant:
public int MyInteger { get; set; }