Is it possible to cheat C# compiler to box Nullable<T> struct ant not its value? - c#

Well, the question may seem odd. And it really is.
Yet I strongly believe that such hacks help in understanding the language and .net platform.
It is how C# compiler treats nullable types implies this question.
Nullable<T> is a struct. But compiler boxes not this struct but the value it holds or just null reference.
It is also intersting how unboxing will work in the case of the boxed Nullable.
Nullable<int> myInt = boxedStruct as Nullable<int>;
here I meen that boxedStruct is not a boxed int but the whole struct.
Well, may be Nullables are treated differently at CLR level because I cannot understand the ouptut of the program below.
class Program
{
public static bool? Property { get; set; }
static void Main(string[] args)
{
Property = true;
var valueType = typeof (Program).GetProperty("Property").GetValue(null).GetType();
var propType = typeof (Program).GetProperty("Property").PropertyType;
Console.WriteLine("Value's type '{0}' is the same as type of the property '{1}' - '{2}'", valueType, propType, valueType == propType);
Console.ReadKey();
}
}
The output:
Value's type 'System.Boolean' is the same as type of the property
'System.Nullable`1[System.Boolean]' - 'False'
Update:
Here what specification (ECMA 335) says:
I.8.2.4 Boxing and unboxing of values ... If the value type
is a nullable type—defined as an instantiation of the value type
System.Nullable—the result is a null reference or bitwise copy of
its Value property of type T, depending on its HasValue property
(false and true, respectively).
So if I understand this correctly. Nullable<T> strcut cannot be boxed in .Net Framework and it's not just impossible with C# compiler but with CLR as well.

I am conjecturing that the question you are trying to ask is:
Can you box a Nullable<int> value without producing a null reference or a boxed int value, but instead an actually boxed Nullable<int>?
No.

Is it possible to cheat C# compiler to box Nullable<T>?
No, as it is not the compiler who does the boxing, it is the CLR. Yes, the boxing of nullable types is specifically handled in the CLR itself.
So is there a way to box a nullable struct without this special handling? Also no.
But it is possible to box another structure that looks like Nullable<T> (ensuring it has the appropriate layout) and with the help of undocumented keywords and memory hacking trick the CLR into thinking the boxed object is actually of Nullable<T>.Beware! This code should be used only for educational purposes. I can't guarantee it will work on other platforms or work at all in different conditions, because it relies on the underlying layout of managed objects.
public static unsafe object BoxNullable<T>(T? nullable) where T : struct
{
object scam = new NullableFake<T>(nullable);
TypedReference tr = __makeref(scam);
IntPtr typehandle = typeof(Nullable<T>).TypeHandle.Value;
IntPtr* trstruct = (IntPtr*)&tr;
**((IntPtr**)trstruct[0]) = typehandle;
return scam;
}
struct NullableFake<T> where T : struct
{
public readonly T? Value;
public NullableContainer(T? nullable)
{
Value = nullable;
}
}
The NullableFake<T> structure has the same layout as Nullable<T>, so it is safe to use it for boxing. TypedReference is used for obtaining a pointer to the variable (that contains a pointer to the object), exposing the object itself. The first value in the object's memory layout is a pointer to the object's type. Overwriting it results in the CLR thinking the type is different.
I don't know any safer way to do it.

Related

Why can I cast an A[] to a B[] if A and B are enum types?

enum makes Code more readable and easy to understand in many case. But I can't understand when I can use this line like below :
public enum A
{
apple,orange,egg
}
public enum B
{
apple,orange,egg
}
public static void main()
{
A[] aa = (A[])(Array) new B[100];
}
Can anyone give me any source code sample where can I used this type of enum Array.
The CLR has more generous casting rules than C# has. Apparently, the CLR allows to convert between arrays of enums if the underlying type has the same size for both types. In the question that I linked the case was (sbyte[])(object)(byte[]) which is similarly surprising.
This is in the ECMA spec Partition I I.8.7 Assignment compatibility.
underlying types – in the CTS enumerations are alternate names for existing types
(§I.8.5.2), termed their underlying type. Except for signature matching (§I.8.5.2)
III.4.3 castclass says
If the actual type (not the verifier tracked type) of obj is verifier-assignable-to the type typeTok
the cast succeeds
castclass is the instruction that the C# compiler uses to perform this cast.
The fact, that the enum members are the same in your example has nothing to do with the problem. Also note, that no new object is being created. It really is just a cast of the object reference.

Is the C# compiler optimizing nullable types?

Can anybody shed any light on why this unit test is failing in Visual Studio 2013?
[TestMethod]
public void Inconceivable()
{
int? x = 0;
Assert.AreEqual(typeof(int?), x.GetType());
}
Your test is failing because:
Calling GetType on a Nullable type causes a boxing operation to be performed when the type is implicitly converted to Object. Therefore GetType always returns a Type object that represents the underlying type, not the Nullable type.
You can read more from How to: Identify a Nullable Type.
Some examples taken from the previous article:
int? i = 5;
Type t = i.GetType();
Console.WriteLine(t.FullName); //"System.Int32"
Also note that:
The C# is operator also operates on a Nullable's underlying type. Therefore you cannot use is to determine whether a variable is a Nullable type. The following example shows that the is operator treats a Nullable<int> variable as an int.
int? i = 5;
if (i is int) { ... } // true
You are correct in presuming that the C# compiler is optimizing nullable types. Here's a quote from Jon Skeet's C# in Depth which should answer your question:
It’s only with respect to boxing and unboxing that the CLR has
any special behavior regarding nullable types. In fact, the behavior was only changed shortly before the release of .NET 2.0, as the result of community requests.
An instance of Nullable is boxed to either a null reference (if it doesn’t have a value) or a boxed value of T (if it does). It never boxes to a “boxed nullable int”—there’s no such type.
There's a similar thread on StackOverflow: Nullable type is not a nullable type?

Use of C# 'ref' keyword compared to C++

I have mainly worked in C++ and I am now using C# at my new job, and after doing some reading on here about the 'ref' keyword and c# value vs reference types I am still finding some confusion with them.
As far as I'm understanding these if you were passing these to a method these would be analogous C++ styles:
Value types:
public void CSharpFunc(value)
and
public void CPlusplusFunc(value)
Reference types:
public void CSharpFunc(reference)
and
public void CPlusPlusFunc(&reference)
'ref' / pointer
public void CSharpFunc(ref bar)
and
public void CPlusPlus(*bar)
Is this a correct analogy?
Is this a correct analogy?
Despite what the other answers say, no. What ref means in terms of C++ actually depends on the type. For value types, your assessment is correct (or close enough). For reference types, a more suitable analogy would be a reference-to-pointer:
public void CPlusPlus(type*& bar)
The whole point about ref is that you can change the reference being passed in. And you can’t do that in C++ by simply passing a pointer:
void f(type* bar) {
bar = new_address;
}
type* x;
f(x);
This code won’t change the caller’s value of x. If you had passed bar as type*&, on the other hand, it would have changed the value. That is what ref does.
Furthermore, a reference in C# is quite unlike a reference in C++, and much more like a pointer in C++ (in that you can change which object the reference refers to).
It would be more accurate (though still not exactly the same) to swap your "Reference types" and "ref" examples.
In C#, a reference type is a type that is always accessed internally via a reference to an instance of the type. It is easiest to thing of these as "pointers" in the C++ sense: you allocate memory, run the constructor(s), and get back a value that indirectly refers to the object you want. The difference between C# and C++ here is that in C#, this is a property of the type, not of the variable. A type is either always a reference type or always a value type. One effect of this is that you don't have to do anything special to use a reference type (there is no "dereference" operator in managed C# code); the compiler assumes that reference type variable access is indirected. In C++ you would still need to use the -> operator, because you can have both value and reference variables of the same type (object x vs. object *x).
The ref keyword is used to pass parameters by reference; those parameters can be either a value type (like int) or a reference type. While the implementation of the ref keyword is ultimately an address-of/pointer-to type operation (exactly as & is in C++), ref (and out) produce a special type of object called a managed reference, which is different from a reference type in that you can have managed references to value types. This is almost exactly the way C++ works: an int& is a special type of "reference to an int" that is distinct from int *, even though both are basically using pointer indirection to access a variable. Similarly, in C# you can have a ref Object, which would be effectively an object *&.
Yes, you are mostly correct, (s/*/*& and you're 100% there). As #weston mentioned, out is an additional keyword to be familiar with. The only cute thing you can do with ref is overload a function that's not ref.
class Person {
string Name { get; set; }
string Address { get; set; }
int age { get; set; }
}
public void UpdateName(Person p)
{
if (p == null)
{
return;
}
p.Name = "Tom";
}
public void UpdateName(ref Person p)
{
if (p == null)
{
p = new Person();
}
p.Name = "Tom";
}
Obviously useless, but it does provide for some interesting opportunities (and bad design). out does not provide the same overload functionality.
If you would like 1 for 1, you can always block your code with unsafe.

Why can an int? set to null have instance properties?

I'm curious as to why the following code works (run under the VS debugger):
int? x = null;
null
x.HasValue
false
If x is indeed null, what instance does HasValue refer to? Is HasValue implemented as an extension method, or does the compiler special case this to make it magically work?
Because x isn't a reference type. The ? is just syntactic sugar for Nullable<T>, which is a struct (value type).
int? is actually a structure Nullable<int>. Hence this, your x cannot be null, because it is always instance of a structure.
Hand-waving answer: Nullable structs are magic.
Longer answer: Null is not actually what is represented by the value. When you assign null to a nullable struct, what you will see happen behind the scenes is different.
int? val = null; // what you wrote
Nullable<Int32> val = new Nullable<Int32>(); // what is actually there
In this case, an instance of the struct is created that has the T Value set to a default value and the bool HasValue property set to false.
The only time you will actually obtain a null reference from a Nullable<T> is when it is boxed, as a Nullable<T> boxes directly to T or null, depending upon if the value is set.
There are several meanings to null.
One in programming languages which present variables and memory in a pointer-based manner (which includes C#'s references though it hides some of the details) is "this doesn't point to anything".
Another is "this has no meaningful value".
With reference types, we often use the former to represent the latter. We might use string label = null to mean "no meaningful label. It remains though that it's still also a matter of what's going on in terms of what's where in memory and what's pointing to it. Still, it's pretty darn useful, what a shame we couldn't do so with int and DateTime in C#1.1
That's what Nullable<T> provides, a means to say "no meaningful value", but at the level below it's not null in the same way a null string is (unless boxed). It's been assigned null and is equal to null so it's logically null and null according to some other semantics, but it's not null in the "doesn't point to anything" implementation difference between reference and value types.
It's only the "doesn't point to anything" aspect of reference-type null that stops you from calling instance methods on it.
And actually, even that isn't strictly true. IL let's you call instance methods on a null reference and as long as it doesn't interact with any fields, it will work. It can't work if it needs (directly or indirectly) those fields since they don't exist on a null refernce, but it could call null.FineWithNull() if that method was defined as:
int FineWithNull()
{
//note that we don't actually do anything relating to the state of this object.
return 43;
}
With C# it was decided to disallow this, but it's not a rule for all .NET (I think F# allows it, but I'm not sure, I know unmanaged C++ allowed it and it was useful in some very rare cases).
When using int? x = null then x is assigned a new instance of Nullable<int> and ist value is set to null.
I don't exactly know the internals but I would assume that the assignment operator itself is somewhat overloaded.
A nullable type isn't actually null since it still doesn't get around the fact that value types can't be null. It is, instead, a reference to the Nullable<> struct (which is also a value type and can't be null).
More information here.
Basically, you're always referring to an instance of something when you use a nullable type. The default information returned by that reference is the stored value (or null if there is no stored value).
Nullable isn't really a reference type, and its instance methods are one of the places where this shows up. Fundamentally, it is a struct type containing a boolean flag and a value of the type it is a nullable of. The languages special-case various operators [to be lifting, or to consider (bool?)null false in some cases] and the null literal, and the runtime special-cases boxing, but apart from that it's just a struct.
It's a completely new type. Nullable is not T.
What you have is a generic class something like this:
public struct Nullable<T>
{
public bool HasValue { get { return Value != null; } }
public T Value { get; set; }
}
I'm sure there's more to it (particularly in the getter and setter, but that's it in a nutshell.
The nullable type (in this case: nullable int) has a property of HasValue which is boolean. If HasValue is True, the Value property (of Type T, in this case, an int) will have a valid value.

Do C# Nullable variables still function as value types?

If I declare a nullable (either via Nullable or the ? symbol) variable from a value type, does it still respect the rules of value types (i.e. pass by value by default, deallocated when it falls out of scope, not when the garbage collector runs) or does it turn into a reference type since it's actually of type Nullable?
The documentation is here:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
As you can see, the documentation describes this as the "nullable structure", indicating that it is a value type. Also, the documentation gives the first lines of the declaration of the type:
public struct Nullable<T> where T : struct, new()
again showing that the type is a value type.
Yes, System.Nullable is a generic Struct, ie value type.
Nullable value types are essentially just a struct wrapper around a value type which allows them to be flagged as null.
something like this:
struct Nullable<T>
{
public T Value;
public bool HasValue;
}
I believe it's actually more complex than that under the hood, and the compiler does lots of nice stuff for you so you can write for example if(myInt == null). But yes, they are still value types.

Categories