My question is: What is the most efficient and correct, for large set of data ?
_pointBuffer1 = new Point3DCollection {
new Point3D(140.961, 142.064, 109.300), new Point3D(142.728, 255.678, (...)
-- or --
_pointBuffer1.Add(new Point3D(140.961, 142.064, 109.300)); _poitBuffer1.Add(142.728, (...)
Or is it the same ?
Point3D is declared as a Point3DCollection, but my question is for any object collection (could be Int32 for example) ..
I would strongly suggest using the collection initializer for the sake of clarity (although I'd use some newlines as well).
They don't quite end up as the same IL, mind you. The first ends up being equivalent to:
var tmp = new Point3DCollection();
tmp.Add(new Point3D(140.961, 142.064, 109.300));
tmp.Add(new Point3D(142.728, 255.678));
...
_pointBuffer1 = tmp;
In other words, the assignment to the eventual variable is only made after all the Add calls.
This is important if your Point3D constructor somehow references _pointBuffer1!
Both are compiled to the same IL. Collection initializers are just syntactic sugar. They will call the Add method. Example:
var res = new List<int>() { 1, 2, 3 };
is compiled to:
List<int> <>g__initLocal0 = new List<int>();
<>g__initLocal0.Add(1);
<>g__initLocal0.Add(2);
<>g__initLocal0.Add(3);
List<int> res = <>g__initLocal0;
The only difference is an additional local variable being declared.
Collection initialisation is syntactic sugar. By this I mean that it is a convenient shorthand that is understood by the complier. The compiler will produce code that is logically identical to calling the collection's add method for each element.
Related
I decompiled some C# 7 libraries and saw ValueTuple generics being used. What are ValueTuples and why not Tuple instead?
https://learn.microsoft.com/en-gb/dotnet/api/system.tuple
https://learn.microsoft.com/en-gb/dotnet/api/system.valuetuple
What are ValueTuples and why not Tuple instead?
A ValueTuple is a struct which reflects a tuple, same as the original System.Tuple class.
The main difference between Tuple and ValueTuple are:
System.ValueTuple is a value type (struct), while System.Tuple is a reference type (class). This is meaningful when talking about allocations and GC pressure.
System.ValueTuple isn't only a struct, it's a mutable one, and one has to be careful when using them as such. Think what happens when a class holds a System.ValueTuple as a field.
System.ValueTuple exposes its items via fields instead of properties.
Until C# 7, using tuples wasn't very convenient. Their field names are Item1, Item2, etc, and the language hadn't supplied syntax sugar for them like most other languages do (Python, Scala).
When the .NET language design team decided to incorporate tuples and add syntax sugar to them at the language level an important factor was performance. With ValueTuple being a value type, you can avoid GC pressure when using them because (as an implementation detail) they'll be allocated on the stack.
Additionally, a struct gets automatic (shallow) equality semantics by the runtime, where a class doesn't. Although the design team made sure there will be an even more optimized equality for tuples, hence implemented a custom equality for it.
Here is a paragraph from the design notes of Tuples:
Struct or Class:
As mentioned, I propose to make tuple types structs rather than
classes, so that no allocation penalty is associated with them. They
should be as lightweight as possible.
Arguably, structs can end up being more costly, because assignment
copies a bigger value. So if they are assigned a lot more than they
are created, then structs would be a bad choice.
In their very motivation, though, tuples are ephemeral. You would use
them when the parts are more important than the whole. So the common
pattern would be to construct, return and immediately deconstruct
them. In this situation structs are clearly preferable.
Structs also have a number of other benefits, which will become
obvious in the following.
Examples:
You can easily see that working with System.Tuple becomes ambiguous very quickly. For example, say we have a method which calculates a sum and a count of a List<Int>:
public Tuple<int, int> DoStuff(IEnumerable<int> values)
{
var sum = 0;
var count = 0;
foreach (var value in values) { sum += value; count++; }
return new Tuple(sum, count);
}
On the receiving end, we end up with:
Tuple<int, int> result = DoStuff(Enumerable.Range(0, 10));
// What is Item1 and what is Item2?
// Which one is the sum and which is the count?
Console.WriteLine(result.Item1);
Console.WriteLine(result.Item2);
The way you can deconstruct value tuples into named arguments is the real power of the feature:
public (int sum, int count) DoStuff(IEnumerable<int> values)
{
var res = (sum: 0, count: 0);
foreach (var value in values) { res.sum += value; res.count++; }
return res;
}
And on the receiving end:
var result = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {result.sum}, Count: {result.count}");
Or:
var (sum, count) = DoStuff(Enumerable.Range(0, 10));
Console.WriteLine($"Sum: {sum}, Count: {count}");
Compiler goodies:
If we look under the cover of our previous example, we can see exactly how the compiler is interpreting ValueTuple when we ask it to deconstruct:
[return: TupleElementNames(new string[] {
"sum",
"count"
})]
public ValueTuple<int, int> DoStuff(IEnumerable<int> values)
{
ValueTuple<int, int> result;
result..ctor(0, 0);
foreach (int current in values)
{
result.Item1 += current;
result.Item2++;
}
return result;
}
public void Foo()
{
ValueTuple<int, int> expr_0E = this.DoStuff(Enumerable.Range(0, 10));
int item = expr_0E.Item1;
int arg_1A_0 = expr_0E.Item2;
}
Internally, the compiled code utilizes Item1 and Item2, but all of this is abstracted away from us since we work with a decomposed tuple. A tuple with named arguments gets annotated with the TupleElementNamesAttribute. If we use a single fresh variable instead of decomposing, we get:
public void Foo()
{
ValueTuple<int, int> valueTuple = this.DoStuff(Enumerable.Range(0, 10));
Console.WriteLine(string.Format("Sum: {0}, Count: {1})", valueTuple.Item1, valueTuple.Item2));
}
Note that the compiler still has to make some magic happen (via the attribute) when we debug our application, as it would be odd to see Item1, Item2.
The difference between Tuple and ValueTuple is that Tuple is a reference type and ValueTuple is a value type. The latter is desirable because changes to the language in C# 7 have tuples being used much more frequently, but allocating a new object on the heap for every tuple is a performance concern, particularly when it's unnecessary.
However, in C# 7, the idea is that you never have to explicitly use either type because of the syntax sugar being added for tuple use. For example, in C# 6, if you wanted to use a tuple to return a value, you would have to do the following:
public Tuple<string, int> GetValues()
{
// ...
return new Tuple(stringVal, intVal);
}
var value = GetValues();
string s = value.Item1;
However, in C# 7, you can use this:
public (string, int) GetValues()
{
// ...
return (stringVal, intVal);
}
var value = GetValues();
string s = value.Item1;
You can even go a step further and give the values names:
public (string S, int I) GetValues()
{
// ...
return (stringVal, intVal);
}
var value = GetValues();
string s = value.S;
... Or deconstruct the tuple entirely:
public (string S, int I) GetValues()
{
// ...
return (stringVal, intVal);
}
var (S, I) = GetValues();
string s = S;
Tuples weren't often used in C# pre-7 because they were cumbersome and verbose, and only really used in cases where building a data class/struct for just a single instance of work would be more trouble than it was worth. But in C# 7, tuples have language-level support now, so using them is much cleaner and more useful.
I looked at the source for both Tuple and ValueTuple. The difference is that Tuple is a class and ValueTuple is a struct that implements IEquatable.
That means that Tuple == Tuple will return false if they are not the same instance, but ValueTuple == ValueTuple will return true if they are of the same type and Equals returns true for each of the values they contain.
In addition to the comments above, one unfortunate gotcha of ValueTuple is that, as a value type, the named arguments get erased when compiled to IL, so they're not available for serialisation at runtime.
i.e. Your sweet named arguments will still end up as "Item1", "Item2", etc. when serialised via e.g. Json.NET.
Other answers forgot to mention important points.Instead of rephrasing, I'm gonna reference the XML documentation from source code:
The ValueTuple types (from arity 0 to 8) comprise the runtime implementation that underlies
tuples in C# and struct tuples in F#.
Aside from created via language syntax, they are most easily created via the
ValueTuple.Create factory methods.
The System.ValueTuple types differ from the System.Tuple types in that:
they are structs rather than classes,
they are mutable rather than readonly, and
their members (such as Item1, Item2, etc) are fields rather than properties.
With introduction of this type and C# 7.0 compiler, you can easily write
(int, string) idAndName = (1, "John");
And return two values from a method:
private (int, string) GetIdAndName()
{
//.....
return (id, name);
}
Contrary to System.Tuple you can update its members (Mutable) because they are public read-write Fields that can be given meaningful names:
(int id, string name) idAndName = (1, "John");
idAndName.name = "New Name";
Late-joining to add a quick clarification on these two factoids:
they are structs rather than classes
they are mutable rather than readonly
One would think that changing value-tuples en-masse would be straightforward:
foreach (var x in listOfValueTuples) { x.Foo = 103; } // wont even compile because x is a value (struct) not a variable
var d = listOfValueTuples[0].Foo;
Someone might try to workaround this like so:
// initially *.Foo = 10 for all items
listOfValueTuples.Select(x => x.Foo = 103);
var d = listOfValueTuples[0].Foo; // 'd' should be 103 right? wrong! it is '10'
The reason for this quirky behavior is that the value-tuples are exactly value-based (structs) and thus the .Select(...) call works on cloned-structs rather than on the originals. To resolve this we must resort to:
// initially *.Foo = 10 for all items
listOfValueTuples = listOfValueTuples
.Select(x => {
x.Foo = 103;
return x;
})
.ToList();
var d = listOfValueTuples[0].Foo; // 'd' is now 103 indeed
Alternatively of course one might try the straightforward approach:
for (var i = 0; i < listOfValueTuples.Length; i++) {
listOfValueTuples[i].Foo = 103; //this works just fine
// another alternative approach:
//
// var x = listOfValueTuples[i];
// x.Foo = 103;
// listOfValueTuples[i] = x; //<-- vital for this alternative approach to work if you omit this changes wont be saved to the original list
}
var d = listOfValueTuples[0].Foo; // 'd' is now 103 indeed
Hope this helps someone struggling to make heads of tails out of list-hosted value-tuples.
Having program with such code :
var subtree = new Tree<int>(5, EnumeratorOrder.BreadthFirstSearch) { 1, 2 };
var tree = new Tree<int>(7, EnumeratorOrder.BreadthFirstSearch) { subtree, 10, 15 };
I сan't understan what means { 1, 2 }?
I сan't understan what means { 1, 2 }
The {1, 2} are Collection Initializers.
They represent a short-hand version of
var temp = new Tree<int>(5, EnumeratorOrder.BreadthFirstSearch);
temp.Add(1);
temp.Add(2);
var subtree = temp;
Note regarding initial assignment to temp: The meaning of assignment is evaluate the left, evaluate the right, do the assignment. Evaluating the right produces side effects, and those effects must be ordered before the effect of the assignment. See comments for a full discussion.
It's a collection initializer.
Collection initializers let you specify one or more element initializers when you initialize a collection class that implements IEnumerable or a class with an Add extension method. The element initializers can be a simple value, an expression or an object initializer. By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.
// x is compiled as an int
var x = 10;
// y is compiled as a string
var y = "Hello";
// z is compiled as int[]
var z = new[] { 0, 1, 2 };
but
// ano is compiled as an anonymous type
var ano = new { x1 = 10, y1 = "Hello" };
ano object's properties created are read-only . I want to figure it out why those properties are read only. suggestions are appreciated ?
EDIT:
var ano1 = new { x1 = 10, y1 = "Hello" };
var ano2 = new { x1 = 10, y1 = "Hello" };
Is that if the new anonymous type has the same number and type of properties in the same order will it be of the same internal type as the first ?
var does not mean "use an anonymous type", it means "Compiler, go figure out the type for me!". In the first three cases, the type is actually a "named" type - System.Int32, System.String, and System.Int32[] (in the last case the type of array's elements is also deduced by the compiler from the type of array elements that you put in the initializer).
The last case is the only one where an anonymous type is used. It is by design that C#'s anonymous types are immutable. The primary case for adding them in the language in the first place has been introduction of LINQ, which does not need mutability in cases when anonymous types are produced. In general, immutable classes tend to give designers less problems, especially when concurrency is involved, so designers of the language decided to go with immutable anonymous types.
Anonymous types are immutable, i.e Can't change.
What is an immutable type?
Eric Lippert's Blog
Interesting statement from here. And an alternative is found here.
... [B]y ensuring that the members do not change, we ensure that the
hash is constant for the lifetime of the object.This allows anonymous
types to be used with collections like hashtables, without actually
losing them when the members are modified. There are a lot of benefits
of immutabilty in that, it drastically simplifies the code that uses
the object since they can only be assigned values when created and
then just used (think threading)
// x is compiled as an int
var x = 10;
// y is compiled as a string
var y = "Hello";
// z is compiled as int[]
var z = new[] { 0, 1, 2 };
but
// ano is compiled as an anonymous type
var ano = new { x1 = 10, y1 = "Hello" };
ano object's properties created are read-only . I want to figure it out why those properties are read only. suggestions are appreciated ?
EDIT:
var ano1 = new { x1 = 10, y1 = "Hello" };
var ano2 = new { x1 = 10, y1 = "Hello" };
Is that if the new anonymous type has the same number and type of properties in the same order will it be of the same internal type as the first ?
var does not mean "use an anonymous type", it means "Compiler, go figure out the type for me!". In the first three cases, the type is actually a "named" type - System.Int32, System.String, and System.Int32[] (in the last case the type of array's elements is also deduced by the compiler from the type of array elements that you put in the initializer).
The last case is the only one where an anonymous type is used. It is by design that C#'s anonymous types are immutable. The primary case for adding them in the language in the first place has been introduction of LINQ, which does not need mutability in cases when anonymous types are produced. In general, immutable classes tend to give designers less problems, especially when concurrency is involved, so designers of the language decided to go with immutable anonymous types.
Anonymous types are immutable, i.e Can't change.
What is an immutable type?
Eric Lippert's Blog
Interesting statement from here. And an alternative is found here.
... [B]y ensuring that the members do not change, we ensure that the
hash is constant for the lifetime of the object.This allows anonymous
types to be used with collections like hashtables, without actually
losing them when the members are modified. There are a lot of benefits
of immutabilty in that, it drastically simplifies the code that uses
the object since they can only be assigned values when created and
then just used (think threading)
This seems like a basic question, but it's still bugging me.
Why doesn't
MyObject [] myobject = new MyObject [10];
allocate 10 objects? Why do we have to call new on each individual object?
myobject [0] = new MyObject();
:::
myobject [9] = new MyObject();
Or am I just making a silly mistake? :)
As far as I am aware, you arent creating 10 objects in the array, you are creating an array with 10 spaces for objects of type "My Object", null is a perfectly acceptable state for an item within the array though.
You're calling the array constructor, which creates an array, not the object constructor ten times.
What constructor on the element type would you like to call? There's no way to provide any parameters as it is. The only constructors being called implicitly are value types (structs) like integers and doubles.
What if the element constructor fails? It could throw any exception. Should you get an half initialized array, or no array at all? Should the exception bubble or be hidden?
What if the element constructor is just very very slow. Add a Thread.Sleep() and the code that calls you would basically hang. How would you debug that?
And my last thought, why are you even using arrays when there's List<T>? =)
It's because it only allocates references to MyObject, not the object itself. That's the case with every non-primitive type in languages like C# or Java.
You could also use the following declaration style (not particularly useful in the following example, I would recommend a for loop instead)
MyObject[] myObject
= new MyObject[]
{ new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject(),
new MyObject()
};
however, in this case it could be easier to type.
int[] myInts = new int[]{ 10,34,13,43,55,2,0,23,6,23 };
That's exactly how it should be done.
For example:
MyObject[] myObject = new MyObject[10]; // creates 10 null references
for (int i=0;i<myobject.Length;i++)
myobject[i] = new MyObject();
Because all you have created is an array with 10 spaces that will contain your MyObject object instances. When will you put those in and in what state, it's up to you.
Looks like your talking about C# from the syntax.
More or less, in the CLR/.NET framework, an array is an array which contain's object's of type MyObject. Unlike C/C++, where an array is an array of objects of type MyObject.
i.e. C# array's are simply container's, conceptually they are they are distinct from the object's they hold. C/C++ (native memory), your pretty much cheating and forgo'ng the formality of having clear seporation of duties... your array is essentially the object it contains....