Jump to content
  • Advertisement
Sign in to follow this  
Programmer One

[.net] .NET 2.0 Bug

This topic is 3664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I think I found a bug in .NET 2.0 (not sure about 3.0 and 3.5) but I can't see to find any articles about this. I am working on something that heavily involves reflection, calling functions in classes that do not exist during compile time, etc, etc. As I was doing this, I found this interesting....quirk: So check this out. I am going to show the code for reproducing the bug as well as explain it. So. All classes, types and such are derived from System.Object. For example:
System.String -> System.Object
System.IO.MemoryStream -> System.IO.Stream -> System.MarshalByRefObject -> System.Object
So, you get my point. Now check this out:
System.Int32 -> System.ValueType -> System.Object
If I create a delegate whose return type is System.Object and then return any instance of System.String, System.IO.MemoryStream...then .NET has absolutely no problems. If you will notice that System.IO.MemoryStream is 3 levels deep in inheritance. So, my delegate has a return type of System.Object, but when I implement this delegate and the return type is System.String or System.IO.MemoryStream or System.GrandmaSpecialCake, we're all fine and dandy. HOWEVER If I try to return a System.ValueType such as System.Int32 or System.Double, .NET has a hissy fit. No no no, you can't do that. Because.....pffft, fuck you. System.Int32 is only 2 levels deep into inheritance from System.Object. Let me show some code:
// Declare some delegate with its return type as System.Object
public delegate object SomeDelegate();


SomeDelegate myDelegate = new SomeDelegate(FunctionReturnsString);
...
myDelegate();
...
// .NET Has Not Problems with This:
public String FunctionReturnsString()
{
    return "123";
}


SomeDelegate myDelegate = new SomeDelegate(FunctionReturnsStream);
...
myDelegate();
...
// .NET Has Not Problems with This:
public System.IO.MemoryStream FunctionReturnsStream()
{
    return new MemoryStream();
}


SomeDelegate myDelegate = new SomeDelegate(FunctionReturnsInt32);
...
myDelegate();
...
// .NET Shits Its Pants:
public Int32 FunctionReturnsInt32()
{
    return 123;
}


So yeah. Interesting stuff. Don't know if this still happens in .NET 3 or 3.5. EDIT: I should mention that the exception occurs when I am creating the delegate that points to these functions. [Edited by - Programmer One on June 11, 2008 6:01:20 PM]

Share this post


Link to post
Share on other sites
Advertisement
Yeah, I don't think that's a bug. You can still return the integer if you want, just change the return value of your function back to "object", and then just return the boxed integer.

My guess is that the compiler can match up other functions that are classes (ie. reference types) because all references will end up being the same size at runtime (essentially a pointer). Value types, on the other hand, can be any size imaginable. How can the runtime ensure that things get passed correctly?

Instead, you just need to handle the boxing to a reference on your own. Not a big deal really, and I'm pretty sure it's not a bug, since the compiler appropriately errors out, and prevents you from breaking anything at runtime.

Share this post


Link to post
Share on other sites
Yeah, that doesn't leap out at me as a bug. Seems like mildly expected behavior if you've any background with unmanaged languages and/or have done some fiddling with delegates under the hood.

Have you tried returning a non-trivial value type? Say... System.DateTime I'd expect that to be more likely to work (though still iffy).

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Yeah, that doesn't leap out at me as a bug. Seems like mildly expected behavior if you've any background with unmanaged languages and/or have done some fiddling with delegates under the hood.

Have you tried returning a non-trivial value type? Say... System.DateTime I'd expect that to be more likely to work (though still iffy).


I tried it, as well as my own structs. It just doesn't want to match the delegate up with functions that return value types. Which is understandable, since the function signature, from a runtime and compiler view, looks nothing like one that returns a reference type.

Share this post


Link to post
Share on other sites
myeh. delegates kinda suck.

Seems like the OP is stuck with some specialization with generic delegates or some adapter to change the return into a nullable...

Share this post


Link to post
Share on other sites
The hierarchy is deceptive; a value type is a value type, not a reference type. That distinction is more important and more fundamental to the language that the derivation from System.ValueType which is more conceptual in nature.

I don't think this is a bug.

Share this post


Link to post
Share on other sites
Well...

There just something about it that just doesn't seem right. I mean, if everything within .NET is supposed to be a subclass of System.Object, even System.ValueType, it would lend itself to the belief that what I am trying to do would work. Even on the conceptual level.

Seems quirky.

Share this post


Link to post
Share on other sites
It's as much as a bug as the following code ;)


int i = null;

The CLR manages value types and reference types in different ways, no matter if they are both subclasses of System.Object (that's why they are allocated on the stack or the heap and why you can't do somethings sometimes).

Regards,

Vicente

Share this post


Link to post
Share on other sites
My 2.0 cents:

The ValueTypes do not inherit from Object.
The reason you can cast a value type to an object and back again is something called boxing and unboxing, NOT inheritance.




Also: ValueTypes are not always allocated on the Stack (as many presume they do) that only happens when the variable is declared in a method or as a parameter. A valuetype that is a member of an class will be allocated in-line in the object on the heap. But this is a side track.

Share this post


Link to post
Share on other sites
Quote:
Original post by ernow
My 2.0 cents:

The ValueTypes do not inherit from Object.
The reason you can cast a value type to an object and back again is something called boxing and unboxing, NOT inheritance.


Your two cents are worthless. ValueType (the base type for all structs) does indeed inherit from System.Object. The reason you can cast a value type to an object is indeed from inheritance. It's how the language works. You can't magically up cast to classes that aren't your parents.

Now, in the case of value types on the stack, you're right that they do, in fact, need to be boxed to be referenced as an implemented interface or the base object class. This is different from the actual cast, however. Boxing merely creates a copy of the data on the managed heap and returns a reference to it. It's the actual casting that allows it to be usable as a different type.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!