What sort of array is this? [duplicate] - c#

// 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)

Related

C#: Why does dynamic help determine type argument for use in generic methods?

I'm working with reflection to create some meta-tests to ensure equality between two instances of the same type.
As such, I'm using a lot of vars and generics.
One thing I've noticed is that with my generic functions, sometimes the Type argument is object (presumably when it can't determine the type) and other times it's the correct type.
Example:
Generic methods
public static RT[] CreateArrayWithNumItems<RT>(RT baseArgument, int numItems)
{
var a = new List<RT>();
for (int i = 0; i < numItems; i++)
a.Add((RT)DataObjectCreator.CreateUninitializedObject(typeof(RT)));
return a.Select(x => (RT)x).ToArray();
} //actual implementation more complex
private static T UnboxObject<T>(T boxedObject)
=> boxedObject;
public static object CreateUninitializedObject(Type typeObject)
=> typeObject == typeof(string) ? "" : FormatterServices.GetUninitializedObject(typeObject);
Use of methods:
var a = Model.GetType();
var unitializedObject = CreateUninitializedObject(a); //returns typed object
var objectArray = CreateArrayWithNumItems(unitializedObject, 1); //returns object array
var uob = UnboxObject(unitializedObject); //returns typed object
var uobObjectArray = CreateArrayWithNumItems(uob, 1); //returns object array
var typedArray = CreateArrayWithNumItems((dynamic) unitializedObject, 1); //returns typed object array
This seems strange to me (a.k.a I'm missing some knowledge), so I have a few questions about it.
Given the same variable, why does UnboxObject return a typed object and CreateArrayWithNumItems return an array of object?
Given the typed object uob why does CreateArrayWithNumItems return an array of object?
Lastly (and most importantly), why does casting to dynamic prior to calling CreateArrayWithNumItems allow the generic method to determine the type?
Without dynamic, the compiler performs all the type evaluations based on static analysis; assuming that CreateUninitializedObject returns object (presumably via FormatterServices), the call to CreateArrayWithNumItems infers the generic type parameters based on that static type, i.e.
var objectArray = CreateArrayWithNumItems(unitializedObject, 1);
becomes
var objectArray = CreateArrayWithNumItems<object>(unitializedObject, 1);
precisely because unitializedObject is object.
With dynamic, the runtime performs the work, but now it has knowledge of the actual object at runtime, so it knows that the type is (whatever Model is). The runtime then constructs something like:
dynamic objectArray = CreateArrayWithNumItems<TheActualType>((TheActualType)unitializedObject, 1);
(how it actually does it is much more complex; it could look for non-generic methods too, for example)
So yes, using dynamic can be a sneaky way to go from reflection (object/Type) code to strongly-typed generic code, but: it has a cost: dynamic involves more work at runtime - additional reflection, and additional runtime IL emit. You also need to be aware that typedArray is now also dynamic (unless you cast it to something else), so everything you do with typedArray becomes dynamic. Increasing costs.

A list of anonymous types with inheritance

Let's say I have the following classes
public class Dog{}
public class Bulldog : Dog{}
public class Pitbull : Dog{}
I am trying to create a list like this
var dogs2 = new[]
{
new { X = new Bulldog(), Y = 10},
new { X = new Pitbull(), Y = 20}
}.ToList();
But, I am getting the following error No best type found for implicitly - typed array
Ok, I guess that makes sense. The system can't figure out that X is a type ofDog`
So, I try doing this
var dogs1 = Enumerable.Empty<object>()
.Select(x => new { X = new Dog (), Y = 0 })
.ToList();
dogs1.Add(new { X = new Pitbull(), Y = 10 });
dogs1.Add(new { X = new Bulldog(), Y = 10 });
Now, I am getting this error cannot convert from '<anonymous type: PassingEvents.Bulldog X, int Y>' to '<anonymous type: PassingEvents.Dog X, int>'. Why can't it convert? Isn't Bulldog castable to Dog?
Is there a way to fix this, without having to crate a new class? The code below works just fine
public class DogCombo
{
public Dog X;
public int Y;
}
var dogs3 = new[]
{
new DogCombo{ X = new Bulldog(), Y = 10},
new DogCombo{ X = new Pitbull(), Y = 20}
}.ToList();
Why can't it convert? Isn't Bulldog castable to Dog?
Bulldog is convertible to Dog, yes.
Your reasoning is as follows:
Bulldog is convertible to Dog
Therefore anonymous-type-with-Bulldog should be convertible to anonymous-type-with-Dog.
This reasoning -- that the properties of the underlying types should imply properties of types under a transformation -- is called covariance.
C# supports covariance in certain restricted cases. They are:
An array of Bulldog may be used as an array of Dog. Note that this is unsafe covariance, because you can put a Poodle into an array of Dog, but not into an array of Bulldog. Array covariance is only safe if you never write to the array.
An IEnumerable<Bulldog> may be converted to IEnumerable<Dog>. This is safe. A sequence of bulldogs is a sequence of dogs. This is also true of a few other generic types, like IEnumerator<T>.
A method which returns a Bulldog may be converted to a delegate for a delegate type that returns a Dog.
C# also supports contravariance in some cases. For example, an IComparable<Dog> may be converted to IComparable<Bulldog>. A thing which can compare dogs can compare bulldogs. Note that this convertibility is going in the opposite direction, hence contra variant.
C# does not support any covariance (or contravariance) on classes, structs or anonymous types.
In theory, C# could support contravariance on anonymous types as you desire; it would be safe to do so. The language and runtime teams have been pitched this feature before. It's simply the case that the language and runtime teams have not prioritized the feature highly enough to actually implement it.
If you think that there is a really good reason to implement covariant conversions on structural types like anonymous types, you can start a discussion on that topic on the Roslyn github forum, and maybe it will be implemented someday.
Is there a way to fix this, without having to create a new class?
I would suggest that you create a new class. But if you want a cheap and easy workaround: just cast explicitly to Dog.
You can explicitly cast X to a type of Dog:
var dogs2 = new[]
{
new { X = (Dog)new Bulldog(), Y = 10},
new { X = (Dog)new Pitbull(), Y = 20}
}.ToList();

Anonymous Types in C#

// 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)

C# reflection and instantiation - is there a way to do Activator.CreateInstance(myType){ X = x }?

I'm not sure of the terminology for this kind of code, but I want to know if it's possible to instantiate variables after the parentheses, but whilst using reflection.
I have a map which gets loaded from an XML file. This is a collection of (int X, int Y, string S) where the X,Y is the position of some terrain, and S is a string representing the type of the terrain. I have a dictionary to pass between the strings and the relevant types; for example one key-value pair might be "Tree", typeof(Tree).
When using reflection, although I know it's possible to instantiate with parameters, the only way I'm comfortable is just by using Activator.CreateInstance(Type t), i.e. with an empty constructor.
When I had the maps hard coded, I would originally instantiate like this (within some i,j for loop):
case: "Tree"
world.Add( new Tree(i,j) );
Whilst starting to think about reflection and my save file, I changed this to:
world.Add( new Tree() { X = i, Y = j }
However, I realised that this won't work with reflection, so I am having to do the following (Tree inherits from Terrain, and the dictionary just converts the XML save data string to a type):
Type type = dictionary[dataItem.typeAsString];
Terrain t = (Terrain)Activator.CreateInstance(type);
t.X = i;
t.Y = j;
world.Add(t);
I would prefer to do this using something like
Type type = dictionary[dataItem.typeAsString];
world.Add((Terrain)Activator.CreateInstance(type) { X = i, Y = j }
Is there any shortcut like this? I guess if not I could edit world.Add to take an X and Y and cast to Terrain in there to access those variables, but I am still curious as to a) what this {var1 = X, var2 = Y} programming is called, and b) whether something similar exists when using reflection.
This syntax is called Object Initializer syntax and is just syntactic sugar for setting the properties.
The code var result = new MyType { X = x } will be compiled to this:
MyType __tmp = new MyType();
__tmp.X = x;
MyType result = __tmp;
You will have to do that yourself using PropertyInfo.SetValue if you know the instantiated type only at runtime or use the normal property setters if the type is known at compile time.
The answer is no, because the object initialization syntax you mention (introduced with LINQ in 3.0) is an illusion of the compiler. As in, when you type this
var foo = new Foo { Bar = "baz" };
the compiler actually converts it into CLS-compliant IL which equates to
var foo = new Foo();
foo.Bar = "baz";
Phil Haack has a great blog post which not only covers the details of this rewriting done by the compiler, but also some side effects it can cause when dealing with types that implement IDisposable
As all of this is nothing but a feint by the compiler, there is no equivalent using reflection (i.e., Activator.CreateInstance(Type t)). Others will give you workarounds, but in the end there really is no direct equivalent.
Probably the closest generic hack you could manage would be to create a method that accepted an object, then used reflection in order to identify the properties of that object and their respective values in order to perform object initialization for you. It might be used something like this
var foo = Supercollider.Initialize<Foo>(new { Bar = "baz" });
and the code would be something like (this is off the top of my head)
public sealed class Supercollider
{
public static T Initialize<T>(object propertySource)
{
// you can provide overloads for types that don't have a default ctor
var result = Activator.CreateInstance(typeof(T));
foreach(var prop in ReflectionHelper.GetProperties(typeof(T)))
ReflectionHelper.SetPropertyValue(
result, // the target
prop, // the PropertyInfo
propertySource); // where we get the value
}
}
You'd have to get each property from the anonymous object, find a property in your target type with the same exact name and type, then get the value from that property in the anonymous object and set the value of your target's property to this value. Its not incredibly hard, but its absolutely prone to runtime exceptions and issues where the compiler chooses a different type for the anonymous type's property, requiring you be more specific (e.g., new { Bar = (string)null }), which screws with the elegance of the thing.
(T)Activator.CreateInstance(typeof(T), param1, param2, ...);
As described HERE.
public sealed class ReflectionUtils
{
public static T ObjectInitializer<T>(Action<T> initialize)
{
var result = Activator.CreateInstance<T>();
initialize(result);
return result;
}
}
public class MyModel
{
public string Name{get;set;}
}
And after that just make the call :
var myModel = ReflectionUtils.ObjectInitializer<MyModel>(m =>
{
m.Name = "Asdf"
});
The advantage is that in this way you will have type safety and use reflection as minimum required, because we all know that reflection is an expensive operation that should be avoided as much as possible.
You could create a constructor which takes those arguments, then use
Activator.CreateInstance(type, i, j)
But you won't be able to use the object initialization syntax. Which is just sugar candy for setting the properties.

When to use value and reference types for immutable types? (.NET)

With mutable types, the difference in behaviour between value and reference types is clear:
// Mutable value type
PointMutStruct pms1 = new PointMutStruct(1, 2);
PointMutStruct pms2 = pms1;
// pms1 == (1, 2); pms2 == (1, 2);
pms2.X = 3;
MutateState(pms1); // Changes the X property to 4.
// pms1 == (1, 2); pms2 == (3, 2);
// Mutable reference type
PointMutClass pmc1 = new PointMutClass(1, 2);
PointMutClass pmc2 = pmc1;
// pmc1 == (1, 2); pmc2 == (1, 2);
pmc2.X = 3;
MutateState(pmc1); // Changes the X property to 4.
// pmc1 == (4, 2); pmc2 == (4, 2);
With immutable types however, this difference is less clear cut:
// Immutable value type
PointImmStruct pis1 = new PointImmStruct(1, 2);
PointImmStruct pis2 = pis1;
// pis1 == (1, 2); pis2 == (1, 2);
pis2 = new PointImmStruct(3, pis2.Y);
// Can't mutate pis1
// pis1 == (1, 2); pis2 == (3, 2);
// Immutable reference type
PointImmClass pic1 = new PointImmClass(1, 2);
PointImmClass pic2 = pic1;
// pic1 == (1, 2); pic2 == (1, 2);
pic2 = new PointImmClass(3, pic2.Y);
// Can't mutate pic1 either
// pic1 == (1, 2); pic2 == (3, 2);
Immutable reference types often use value semantics too (e.g. the canonical example System.String):
string s1 = GenerateTestString(); // Generate identical non-interned strings
string s2 = GenerateTestString(); // by dynamically creating them
// object.ReferenceEquals(strA, strB)) == false;
// strA.Equals(strB) == true
// strA == strB
Eric Lippert has discussed before on his blog (e.g. here) that the fact that value types are often (when doesn't really matter for this discussion) allocated on the stack is an implementation detail and that it shouldn't generally dictate whether you make an object a value or reference type.
Given this blurred distinction in behaviour for immutable types, what criteria does this leave for us to decide whether to make an immutable type a reference type or a value type?
Also, with the immutable emphasis on values vs variables, should immutable types always implement value semantics?
I would say that Eric's blog post you link gives you exactly the answer:
I regret that the documentation does
not focus on what is most relevant; by
focusing on a largely irrelevant
implementation detail, we enlarge the
importance of that implementation
detail and obscure the importance of
what makes a value type semantically
useful. I dearly wish that all those
articles explaining what “the stack”
is would instead spend time explaining
what exactly “copied by value” means
and how misunderstanding or misusing
“copy by value” can cause bugs.
If your objects should have a "copy-by-value" semantic, then make them value types. If they should have a "copy-by-reference" semantic, make them reference types.
He also says this, which I agree with:
I’d always make the choice of value
type vs reference type based on
whether the type is semantically
representing a value or semantically a
reference to something.
There is an important category of immutable types (that Eric Lippert has also written about at some length) that must be implemented as reverence types: recursive types such as list nodes, tree nodes, and the like. Value types can't have cyclical definitions, as, for example, a linked list node does:
class IntNode
{
private readonly int value;
private readonly IntNode next;
}
.NET sort of hints at an answer to this with the String class. It’s immutable, but is a reference type. Make your immutable type act like a value type as much as possible. It doesn’t matter if it actually is a value type.
So the only criteria I can think of is: If copying it is going to be expensive (a String could involve a lot of copying!), make it a reference type. If it’s quick to copy, go for a value type. Also consider if you need to compare references – that’s probably the only tricky part with immutable reference types.

Categories

Resources