I saw a few days ago this syntax and wondered if someone could tell me how it is called, how does it work and where is it useful.
When I ask how does it work I mean that the Setters property is readonly(get),
And the second is what do this braces mean: "Setters = {".
http://msdn.microsoft.com/en-us/library/ms601374.aspx
Thanks
datagrid.CellStyle = new Style(typeof(DataGridCell))
{
// Cancel the black border which appears when the user presses on a cell
Setters = { new Setter(Control.BorderThicknessProperty, new Thickness(0)) } // End of Setters
} // End of Style
It is call object initializer and collection initializer and it allows you to set properties in the { .. } block when calling a constructor. Inside the block, you're using Setters = { ... } which is a collection initializer - it allows you to specify elements of a collection (here, you don't have to create a new instance of the collection - it just adds elements in curly braces). For more information see this MSDN page.
In general, the syntax of object initializers has a few options:
// Without explicitly mentioning parameter-less constructor:
new A { Prop1 = ..., Prop2 = ... }
// Specifying constructor arguments:
new A(...) { Prop1 = ..., Prop2 = ... }
The syntax for collection initializers looks like this:
// Creating new instance
new List<int> { 1, 2, 3 }
// Adding to existing instance inside object initializer:
SomeList = { 1, 2, 3 }
It is worth mentioning that this is closely related to anonymous types (where you don't give a type name - the compiler generates some hidden type and you can work with it using var):
// Create anonymous type with some properties
new { Prop1 = ..., Prop2 = ... }
All of these features are new in C# 3.0. See also this SO post which explains some tricky aspect of collection initializers (in the style you're using them).
instantiated the new object Style, and than setting its property Setters It's a c# 3.0 feature.
It seems to be setting default values when the object is being made. This is kind of like passing values to the constructor, but you aren't limited to just the options the constructor gives you.
Related
I've came across this code:
var rectangle = new Rectangle(420, 69);
var newOne = rectangle with { Width = 420 }
I was wondering about with keyword in C# code. What is it for? And how can it be used? And what benefits does it bring to the language?
It's an operator used in expressions for easier duplication of an object, overriding some of it's public properties/fields (optional)
with expression - MSDN
Currently it can only be used with records. But maybe there will be no such restriction in the future (assumption).
Here's an example how it can be used:
// Declaring a record with a public property and a private field
record WithOperatorTest
{
private int _myPrivateField;
public int MyProperty { get; set; }
public void SetMyPrivateField(int a = 5)
{
_myPrivateField = a;
}
}
Now let's see how with operator can be used:
var firstInstance = new WithOperatorTest
{
MyProperty = 10
};
firstInstance.SetMyPrivateField(11);
var copiedInstance = firstInstance with { };
// now "copiedInstance" also has "MyProperty" set to 10 and "_myPrivateField" set to 11.
var thirdCopiedInstance = copiedInstance with { MyProperty = 100 };
// now "thirdCopiedInstance " also has "MyProperty" set to 100 and "_myPrivateField" set to 11.
thirdCopiedInstance.SetMyPrivateField(-1);
// now "thirdCopiedInstance " also has "MyProperty" set to 100 and "_myPrivateField" set to -1.
NOTE for reference types from MSDN:
In the case of a reference-type member, only the reference to a member instance is copied when an operand is copied. Both the copy and original operand have access to the same reference-type instance.
That logic can be modified by modifying the copy constructor of a record type. Quote from MSDN:
By default, the copy constructor is implicit, that is, compiler-generated. If you need to customize the record copy semantics, explicitly declare a copy constructor with the desired behavior.
protected WithOperatorTest(WithOperatorTest original)
{
// Logic to copy reference types with new reference
}
And in terms of what benefits it gives, I think it should be quite obvious now, that it makes copying of instances much easier and convenient.
Basically, the with operator will create a new object instance (records only, for now), by "coping values" from the "source" object and override some named properties in the destination object.
For example, instead of doing this:
var person = new Person("John", "Doe")
{
MiddleName = "Patrick"
};
var modifiedPerson = new Person(person.FirstName, person.LastName)
{
MiddleName = "William"
};
you can do this:
var modifiedPerson = person with
{
MiddleName = "Patrick"
};
Basically, you will write less code.
Use this source to get more details on the example above and official documentation for more examples.
Short answer is the following:
with keyword in C# was added for easier copy of complicated objects, with a possibility to override some of the public properties.
Examples are already briefly provided in the accepted answer.
I have class and there are a lot of properties in it. Is there a functionality of visual studio to reach all the properties easily. I do not want to use a constructor.
This is the class:
Assignment a = new Assignment()
{
}
And this is what I want to do automaticly so i can fill the values:
Assignment a = new Assignment()
{
prop1 = ,
prop2 = ,
prop3 = ,
prop4 = ,
prop5 =
//...
};
If you need to ensure that all properties are filled, I would use a constructor.
If you do not require all properties or prefer to use an object initialiser, then the closest solution would be ReSharper's Control+Space, which brings up each property. As you select them (and assign them) the list gets shorter, so you only select from the remaining unassigned properties. I am not sure if there is a better way.
I know this is basic, but I'm not getting it. I simply wish to initialize the dependency property Dashes as a double collection using the lambda operator.
What is the proper syntax?
Thank you.
public static readonly DependencyProperty DashesProperty =
DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock),
new UIPropertyMetadata(
() =>
{
DoubleCollection d = new DoubleCollection();
d.Add(4);
d.Add(4);
return d;
}
));
First of all you should avoid passing default value for reference types in DP metadata because that will be shared across all instances of containing class which you didn't intend to.
Say, you declared two instances of CustomTextBlock, then both instances will refer to same list and any modification in list will be transparent to both instances. Unless you explicitly setting it from constructor or somewhere else.
Be careful with default values of DP for reference types.
Anyhow, if you still want it, here how it is done:
new UIPropertyMetadata(new DoubleCollection() { 4, 5 })
UPDATE:
If you pass default value in metadata, then DoubleCollection's gets freezed automatically i.e. you can't add/delete from the collection in that case.
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Will throw exception.
However, if you set it explicitly from constructor, it's not marked as Frozen and items can be added/deleted from the collection.
var dashesCollection = new CustomTextBlock().Dashes.Add(5); // Works fine.
So, essence is to set the value in constructor and not in metadata of DP identifier.
Unfortunately, that's not possible. You can only provide a value, not a value factory. The workaround is to initialize the property in the constructor:
public CustomTextBlock()
{
Dashes = new DoubleCollection {4, 4};
}
Actually, I just realized that since DoubleCollection is Freezable, passing an instance of DoubleCollection as the default value (as suggested by Rohit Vats) could work, as long as you call Freeze on it. You could do it like this:
public static readonly DependencyProperty DashesProperty =
DependencyProperty.Register("Dashes", typeof(DoubleCollection), typeof(CustomTextBlock),
new UIPropertyMetadata(CreateDefaultDashes()));
private static DoubleCollection CreateDefaultDashes()
{
var dashes = new DoubleCollection { 4, 4 };
dashes.Freeze();
return dashes;
}
This makes the collection immutable, which means it can safely be shared among instances of CustomTextBlock.
OK, actually it seems that the default value is automatically frozen, so you don't need to do anything special. It is safe as a default value, because it becomes immutable when it's frozen.
Sometimes an initializer list is specified after the class name without using the () operator:
Cat cat = new Cat { Age = 10, Name = "Fluffy" }
Other times it is specified after the () operator:
List<Cat> cats = new List<Cat>
{
new Cat(){ Name = "Sylvester", Age=8 }
}
I am assuming the difference is because here new Cat() is inside the list. But I still don't understand why it should be different. So why the difference, and when to use which syntax?
Thanks.
When you use the initializer list you can omit the (), when using a parameterless constructor. It does not matter with the new Cat() is inside the list or not.
You must specify the () when there is no default (parameterless) constructor - when you have to supply parameters.
When a class has default constructor (or a parameterless one), you can always omit the () when using an initializer. The compiler does the magic for you and you can think of things as - the compiler inserts them for you.
There is no real difference to which of the two you decide to use. Compare these two Cat instances:
var catA = new Cat(); // traditional constructor
catA.Name = "Mittens"; // set property
var catB = new Cat { Name = "Not Mittens" }; // all in one initializer
They are identical in functionality, just a shortcut notation. The first way is the traditional way, which most object-oriented (OO) languages create objects using the constructor. C# recently has added this new method of creating objects and setting properties to make code cleaner.
Even if your class does not have a parameterless constructor (new()), you can use the {...} initialization still.
Consider this:
var dogA = new Dog("Fido");
var dogA.Age = 12;
var dogB = new Dog("Not Fido") { Age = 7 };
Even if parameters are required in the constructor, you can still use this style of initialization as long as you supply them.
I'm using an API that has a method that requires this type of argument:
System.Collections.ObjectModel.Collection<GenericTickType> genericTickList
How do I instantiate an object for that argument? Here's what I've tried but it keeps saying that the method call has some invalid arguments.
List<TickType> ticks_to_get = new List<TickType> { TickType.Price };
I've tried instantiating a Collection directly instead of a List and that doesn't seem to work.
"I've tried instantiating a Collection directly instead of a List and that doesn't seem to work."
What error do you get? You can definitely create an instance of Collection<T> directly, it is not an abstract class and it has several public constructors, including one that's parameter-less. You can do this, for example:
var values = new System.Collections.ObjectModel.Collection<int> { 1,2,3,4 };
I noticed your sample code has a GenericTickType and a TickType. Is this a mistake or do you actually have two classes? You said it's an enum (which one?), so one cannot possibly derive from the other. If they are two enum types, Collection<GenericTickType> and Collection<TickType> are two different classes and one is not assignable to the other.
Now, if TickType is castable to GenericTickType (and they probably are if they are both enums, and assuming they share the same numeric values), you still cannot cast Collection<TickType> to Collection<GenericTickType>. There's no contra/co-variance in C# for most classes yet (coming in C# 4). But you could cast each TickType by doing something like this:
List<GenericTickType> list = new List<GenericTickType> { (GenericTickType)TickType.Price };
list.Add((GenericTickType)TickType.Price); // add more...
Collection<GenericTickType>genericTicks = new Collection<GenericTickType>(list);
If you already have a List<TickType> and have access to C# 3.0 and LINQ, you can do this:
List<TickType> ticks = new List<TickType> { TickType.Price };
list.Add(TickType.Price); // add more...
List<GenericTickType> castedList = ticks.Cast<GenericTickType>().ToList();
Collection<GenericTickType>genericTicks = new Collection<GenericTickType>(castedList);
This uses the LINQ Cast<T>() and ToList<T>() extension methods to cast each TickType in the original list to GenericTickType and creating a new List<GenericTickType> which is used to instantiate the Collecion<GenericTickType>. (I avoided using var so you could see the types in each step).
You can't pass a List<> as a Collection<>
Maybe you have problems with covariance/contravariance? You have to do the cast on your own:
List<TickType> ticks_to_get = new Collection<TickType> { TickType.Price };
genericTickList = (Collection<GenericTickType>) ticks_to_get;
Look at Dave Bauman's answer ... unless TickType.Price doesn't return an object of type TickType it will not work
EDIT: Since GenericTickType is an enum - which API are you using? Is it of your company - can you change it? It seems to be strange that you are asked to pass a collection of enum values. See, if you can change the enum to a flagged enum ... and then pass the required values by combining them with the or-operator.
What is the type of GenericTickType? Is it an enum or class? I am assuming enum. If that is the case, modify your code as such:
Collection<GenericTickType> ticks_to_get = new Collection<GenericTickType>() { GenericTickType.Price };
The above works on 3.5 framework.
You can't use {} to initialize a Collection. You can do something like this, however:
List<TickType> ticks_to_get =
new List<TickType>( new TickType[] { TickType.Price });
or
List<TickType> ticks_to_get = new List<TickType>();
ticks_to_get.Add(TickType.Price);