C# - Type objects of constructed classes - c#

I've read that reference types all use the same constructed class:
Generics work somewhat differently for reference types. The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with object references substituted for the parameters in the MSIL. Then, every time that a constructed type is instantiated with a reference type as its parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the generic type. This is possible because all references are the same size. (Generics in the Run Time (C# Programming Guide))
However when calling GetType() on constructed objects based on the same generic with different type parameters, two different types are recieved. Where A and B are both classes, and RefType is a generic:
RefType<A> a = new RefType<A>();
RefType<B> b = new RefType<B>();
Console.WriteLine("a type is "+a.GetType());
Console.WriteLine("b type is "+b.GetType());
results in:
"a type is RefType`1[A]"
"b type is RefType`1[B]"
Does this mean that the CLR handles the creation of Type objects for different constructed types even when there is no "real" specialized instantiation?
Is there a way to see directly what is and isn't generated by the CLR?

Does this mean that the CLR handles the creation of Type objects for different constructed types even when there is no "real" specialized instantiation?
Yes. Consider that run-time type checks are an important part of the language.
var x = new List<string>() as List<object>;
This is supposed to initialise x to null. If the run-time type information for new List<string>() had somehow lost the generic type parameter, this couldn't work.
Is there a way to see directly what is and isn't generated by the CLR?
class G<T> { public void f() { } }
class A { }
class B { }
struct C { }
struct D { }
enum E : int { }
static void Main(string[] args)
{
Console.WriteLine(typeof(G<object>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<string>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<A>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<B>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<C>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<D>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<E>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<int>).GetMethod("f").MethodHandle.Value);
}
You will see that G<object>.f, G<string>.f, G<A>.f and G<B>.f have the same method handle, but G<C>.f, G<D>.f, G<E>.f and G<int>.f all have different ones. Not even G<E>.f and G<int>.f share the implementation.

The Type objects give a type information at a high level of abstraction and tell you what the type is logically, whereas the implementation of generics is a low-level detail, that you should not rely on. Implementation details can always change.
T<A> and T<B> are two different types and therefore they must be described by to different Type objects. This is because a Type object not only yields information for T<>, but also for A or B, i.e. for the generic type parameters. The fact that the 2 types share the same code base makes no difference.
Type objects belong to the API. You can use this information in your code. The Type class might be extended in future to reflect new features of the language, but this is not a breaking change.
It is good to know the implementation details when you want to write efficient code. Some low-level tools (O/R-mappers, code weavers etc.); however, do sometimes depend on implementation details.

Related

How can c# share the generic implementations of reference types when 'typeof' and 'is' are used?

As far as I understand, at runtime the CLR implementation creates different machine code (or whatever runtime representation) for the same generic Type with different parameterized valuetypes, but shares the machine code for reference types. This makes sense since reference types are going to take up the same size (the size of a reference).
What I don't understand is how this can work with code that explicitly uses code which depends on the type of T directly through something like typeof(T) or is T. For example, in the class:
class TestClass<T>
{
public static bool TestAType(Object pObj) { return pObj is T; }
}
I don't see how the same implementation for T = List and T = String can allow TestClass<String>.TestAType("hello") to be true and TestClass<List<int>>.TestAType("hello") to be false.
I'm making the assumption here that the machine code is the same for the compiled generic types, which could of course be false.
The native code generated for each generic instantiation using reference types is indeed the same (having System.__Canon as the parameter internally) but that doesn't mean the code should have no access to the original type arguments. The native code can access the metadata via helper functions and retrieve the types.
It would be useful to examine actual native code generated by such a method, but from browsing the SSCLI, it looks like this function does the job, according to its description:
// Given information about how to do a runtime lookup, generate the tree
// for the runtime lookup.
//
// Run-time lookup is required if the enclosing method is shared between instantiations
// and the token refers to formal type parameters whose instantiation is not known
// at compile-time.

How generic methods gets instantiated in C#?

Suppose I've a generic method as:
void Fun<T>(FunArg arg) {}
Are this.Fun<Feature> and this.Fun<Category> different instantiations of the generic method?
In general, how does the generic method get instantiated? Different generic argument produces different method, or same method along with different metadata which is used at runtime?
Please support your answer with some quote(s) from the language specification.
Also, suppose I did these:
client.SomeEvent += this.Fun<Feature>; //line1
client.SomeEvent += this.Fun<Category>; //line2
client.SomeEvent += this.Fun<Result>; //line3
then later on,
client.SomeEvent -= this.Fun<Feature>; //lineX
Does the lineX undo the thing which I did at line1? Or it depends on somethig else also?
They all share a method definition, but at runtime they are different MethodInfo - because the generic type arguments define a generic method.
Supporting illustration:
Action<FunArg> a1 = Fun<X>;
Action<FunArg> a2 = Fun<Y>;
Action<FunArg> a3 = Fun<Y>;
Console.WriteLine(a1.Method == a2.Method); // false
Console.WriteLine(a3.Method == a2.Method); // true
At the JIT level, it is more complex; any reference-type parameters will share an implementation, as a reference is a reference is a reference (noting that all such T must satisfy any constraints in advance). If there are value-type T, then every combination of generic type arguments gets a separate implementation at runtime, since each requires a different final implementation.
It depends on the types involved.
For all the reference types (ie. classes), one method will be JITted to handle them all.
For all the value types (ie. structs), one method per type will be JITted.
So the information in the question is not detailed enough to answer, if Feature and Category are reference types, then yes, one method will be JITted for them. If one of them, or both, are value types, one method per value type will be JITted.
Note my use of the word JITted here. In the assembly compiled, there will be only one method, but at runtime, the JITter will create actual implementations of the generic methods according to the above rules.
Pop Quiz: What happens if you use NGEN on an assembly with generic types/methods? (hint: not what you think)
Yes, they will become two separate methods.

dynamic vs object type

I have used the dynamic and the object type interchangeably. Is there any difference between these two types? Is there any performance implications of using one over the other? Which one of these is more flexible?
They're hugely different.
If you use dynamic you're opting into dynamic typing, and thus opting out of compile-time checking for the most part. And yes, it's less performant than using static typing where you can use static typing.
However, you can't do much with the object type anyway - it has hardly any members. Where do you find yourself using it? When you want to write general purpose code which can work with a variety of types, you should usually consider generics rather than object.
With the advancement in C# language, we have seen the dynamic and object types. Here are the two types, as I learned by comparing these 7 points:
Object
Microsoft introduced the Object type in C# 1.0.
It can store any value because "object" is the base class of all types in the .NET framework.
Compiler has little information about the type.
We can pass the object type as a method argument, and the method also can return the object type.
We need to cast object variables to the original type to use it and to perform desired operations.
Object can cause problems at run time if the stored value is not converted or cast to the underlying data type.
Useful when we don't have more information about the data type.
Dynamic
Dynamic was introduced with C# 4.0
It can store any type of variable, similar to how Visual Basic handles a variable.
It is not type-safe, i.e., the compiler doesn't have any information about the type of variable.
A method can both accept a Dynamic type as an argument and return it.
Casting is not required, but you need to know the properties and methods related to stored type.
The Dynamic type can cause problems if the wrong properties or methods are accessed because all the information about the stored value is resolved at run time, compared to at compilation.
Useful when we need to code using reflection or dynamic languages or with the COM objects due to writing less code.
Hopefully, this would help somebody.
In simple language:
Assume we have the following method:
public static void ConsoleWrite(string inputArg)
{
Console.WriteLine(inputArg);
}
Object: the following code has compile error unless cast object to string:
public static void Main(string[] args)
{
object obj = "String Sample";
ConsoleWrite(obj);// compile error
ConsoleWrite((string)obj); // correct
Console.ReadKey();
}
dynamic: the following code compiles successfully but if it contains a value except string it throws Runtime error
public static void Main(string[] args)
{
dynamic dyn = "String Sample";
ConsoleWrite(dyn); // correct
dyn = 1;
ConsoleWrite(dyn);// Runtime Error
Console.ReadKey();
}
There is an article explaining the different types, including object and dynamic types. The article also explains the difference between the two with a nice example.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types
I shall give a short gist of the difference explained in the article:
The object type is an alias for System.Object in .NET. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from System.Object. You can assign values of any type to variables of type object.
The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Instead, these operations are resolved at run time. The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at run time.
Summary:
What this essentially means is object is a type and all other types inherit from it.
Dynamic is not really a type, it is more like a pointer or representation of some other type, which will be resolved at run time.
Dynamic: Casting is not required but you need to know the property and methods related to stored type to avoid error in run time.
dynamic dyn = 1;
Console.WriteLine(dyn);
int a = dyn;// works fine
Console.WriteLine(a);//print 1
Console.ReadKey();
The above code will work just fine but if dyn = 1.2 is supplied then it will throw exception as 1.2 cannot converted to int
Object: Require to cast object variable explicitly.
object ob = 1;//or 1.2
Console.WriteLine(ob);
int a = ob;//Compile error because explicit casting is not done
Console.WriteLine(a);
Console.ReadKey();
Fiddle: https://dotnetfiddle.net/l5K4Cl

Why it isn't possible to declare a method parameter as var type

I wonder why it is not possible a method parameter as var type like
private void myMethod(var myValue) {
// do something
}
You can only use var for variables inside the method body. Also the variable must be assigned at declaration and it must be possible to deduce the type unambiguously from the expression on the right-hand side.
In all other places you must specify a type, even if a type could in theory be deduced.
The reason is due to the way that the compiler is designed. A simplified description is that it first parses everything except method bodies and then makes a full analysis of the static types of every class, member, etc. It then uses this information when parsing the method bodies, and in particular for deducing the type of local variables declared as var. If var were allowed anywhere then it would require a large change to the way the compiler works.
You can read Eric Lippert's article on this subject for more details:
Why no var on fields?
Because the compiler determines the actual type by looking at the right hand side of the assignment. For example, here it is determined to be a string:
var s = "hello";
Here it is determined to be Foo:
var foo = new Foo();
In method arguments, there is no "right hand side of the assignment", so you can't use var.
See the posting by Eric Lippert about why var is not allowed on fields, which also contains the explanation why it doesn't work in method signatures:
Let me give you a quick oversimplification of how the C# compiler works. First we run through every source file and do a "top level only" parse. That is, we identify every namespace, class, struct, enum, interface, and delegate type declaration at all levels of nesting. We parse all field declarations, method declarations, and so on. In fact, we parse everything except method bodies; those, we skip and come back to them later.
[...]
if we have "var" fields then the type of the field cannot be determined until the expression is analyzed, and that happens after we already need to know the type of the field.
Please see Juliet's answer for a better answer to this question.
Because it was too hard to add full type inference to C#.
Other languages such as Haskell and ML can automatically infer the most general type without you having to declare it.
The other answers state that it's "impossible" for the compiler to infer the type of var but actually it is possible in principle. For example:
abstract void anotherMethod(double z, double w);
void myMethod<T>(T arg)
{
anotherMethod(arg, 2.0); // Now a compiler could in principle infer that arg must be of type double (but the actual C# compiler can't)
}
Have "var" method parameters is in principle the same thing as generic methods:
void myMethod<T>(T arg)
{
....
}
It is unfortunate that you can't just use the same syntax for both but this is probably due to the fact that that C#'s type inference was added only later.
In general, subtle changes in the language syntax and semantics can turn a "deterministic" type inference algorithm into an undecidable one.
ML, Haskell, Scala, F#, SML, and other languages can easily figure out the type from equivalent expressions in their own language, mainly because they were designed with type-inference in mind from the very start. C# wasn't, its type-inference was tacked on as a post-hoc solution to the problem of accessing anonymous types.
I speculate that true Hindley-Milner type-inference was never implemented for C# because its complicated to deduce types in a language so dependent on classes and inheritance. Let's say I have the following classes:
class Base { public void Print() { ... } }
class Derived1 : Base { }
class Derived2 : Base { }
And now I have this method:
var create() { return new Derived1(); }
What's the return type here? Is it Derived1, or should it be Base? For that matter, should it be object?
Ok, now lets say I have this method:
void doStuff(var someBase) { someBase.Print(); }
void Main()
{
doStuff(new Derived1());
doStuff(new Derived2()); // <-- type error or not?
}
The first call, doStuff(new Derived1()), presumably forces doStuff to the type doStuff(Derived1 someBase). Let's assume for now that we infer a concrete type instead of a generic type T.
What about the second call, doStuff(new Derived1())? Is it a type error, or do we generalize to doStuff<T>(T somebase) where T : Base instead? What if we made the same call in a separate, unreferenced assembly -- the type inference algorithm would have no idea whether to use the narrow type or the more genenarlized type. So we'd end up with two different type signatures based on whether method calls originate from inside the assembly or a foreign assembly.
You can't generalize wider types based on usage of the function. You basically need to settle on a single concrete type as soon as you know which concrete type is being pass in. So in the example code above, unless you explicitly cast up to the Base type, doStuff is constrained to accept types of Derived1 and the second call is a type error.
Now the trick here is settling on a type. What happens here:
class Whatever
{
void Foo() { DoStuff(new Derived1()); }
void Bar() { DoStuff(new Derived2()); }
void DoStuff(var x) { ... }
}
What's the type of DoStuff? For that matter, we know based on the above that one of the Foo or Bar methods contain a type error, but can you tell from looking which has the error?
Its not possible to resolve the type without changing the semantics of C#. In C#, order of method declaration has no impact on compilation (or at least it shouldn't ;) ). You might say instead that the method declared first (in this case, the Foo method) determines the type, so Bar has an error.
This works, but it also changes the semantics of C#: changes in method order will change the compiled type of the method.
But let's say we went further:
// Whatever.cs
class Whatever
{
public void DoStuff(var x);
}
// Foo.cs
class Foo
{
public Foo() { new Whatever().DoStuff(new Derived1()); }
}
// Bar.cs
class Bar
{
public Bar() { new Whatever().DoStuff(new Derived2()); }
}
Now the methods is being invoked from different files. What's the type? Its not possible to decide without imposing some rules on compilation order: if Foo.cs gets compiled before Bar.cs, the type is determined by Foo.cs.
While we can impose those sorts of rules on C# to make type inference work, it would drastically change the semantics of the language.
By contrast, ML, Haskell, F#, and SML support type inference so well because they have these sorts of restrictions: you can't call methods before they're declared, the first method call to inferred functions determines the type, compilation order has an impact on type inference, etc.
The "var" keyword is used in C# and VB.NET for type inference - you basically tell the C# compiler: "you figure out what the type is".
"var" is still strongly typed - you're just too lazy yourself to write out the type and let the compiler figure it out - based on the data type of the right-hand side of the assignment.
Here, in a method parameter, the compiler has no way of figuring out what you really meant. How? What type did you really mean? There's no way for the compiler to infer the type from the method definition - therefore it's not a valid statement.
Because c# is type safe and strong type language. At any place of your program compiler always knows the type of argument you are using. var keyword was just introduced to have variables of anonymus types.
Check dynamic in C# 4
Type inference is type inference, either in local expressions or global / interprocedural. So it isn't about "not having a right hand side", because in compiler theory, a procedure call is a form of "right hand side".
C# could do this if the compiler did global type inference, but it does not.
You can use "object" if you want a parameter that accepts anything, but then you need to deal with the runtime conversion and potential exceptions yourself.
"var" in C# isn't a runtime type binding, it is a compile time feature that ends up with a very specific type, but C# type inference is limited in scope.

Anonymous Types

I have a Dictionary(TKey, TValue) like
Dictionary<int, ArrayList> Deduction_Employees =
new Dictionary<int, ArrayList>();
and later I add to that array list an anonymous type like this
var day_and_type = new {
TheDay = myDay,
EntranceOrExit = isEntranceDelay
};
Deduction_Employees[Employee_ID].Add(day_and_type);
Now how can I unbox that var and access those properties ??
First, you aren't unboxing the type. Anonymous types are reference types, not structures.
Even though you can technically create instances of the same type outside of the method they were declared in (as per section 7.5.10.6 of the C# 3.0 Language Specification, which states:
Within the same program, two anonymous
object initializers that specify a
sequence of properties of the same
names and compile-time types in the
same order will produce instances of
the same anonymous type.
) you have no way of getting the name of the type, which you need in order to perform the cast from Object back to the type you created. You would have to resort to a cast-by-example solution which is inherently flawed.
Cast-by-example is flawed because from a design standpoint, every single place you want to access the type outside the function it is declared (and still inside the same module), you have to effectively declare the type all over again.
It's a duplication of effort that leads to sloppy design and implementation.
If you are using .NET 4.0, then you could place the object instance in a dynamic variable. However, the major drawback is the lack of compile-time verification of member access. You could easily misspell the name of the member, and then you have a run-time error instead of a compile-time error.
Ultimately, if you find the need to use an anonymous type outside the method it is declared in, then the only good solution is to create a concrete type and substitute the anonymous type for the concrete type.
There are several ways.
Since the comments seems to indicate that I suggest you do this, let me make it clear: You should be creating a named type for your object since you intend to pass it around.
First, you can use Reflection, which another answer here has already pointed out.
Another way, which tricks .NET into giving you the right type is known as "cast by example", and it goes something like this: You need to pass your object through a generic method call, which will return the object as the right type, by inferring the right type to return.
For instance, try this:
private static T CastByExample<T>(T example, object value)
{
return (T)value;
}
and to use it:
var x = CastByExample(new { TheDay = ??, EntranceOrExit = ?? }, obj);
for the two ?? spots, you just need to pass something fitting the data type for those properties, the values will not be used.
This exploits the fact that multiple anonymous types containing the exact same properties, of the same type, in the same order, in the same assembly, will map to the same single type.
However, by this time you should be creating a named type instead.
An anonymous type has method scope. To pass an anonymous type, or a collection that contains anonymous types, outside a method boundary, you must first cast the type to object. However, this defeats the strong typing of the anonymous type. If you must store your query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.
Source: http://msdn.microsoft.com/en-us/library/bb397696.aspx
No you can't. You can only access the properties by using reflection. The compiler has no way of knowing what the type was, and since it's an anonymous type, you can't cast it either.
If you are using .NET 1.x - 3.x, you must use reflection.
If you use .NET 4.0, you could use a dynamic type and call the expected properties.
In neither case do you need to unbox; that's for value types. Anonymous types are always reference types.

Categories

Resources