Coffeehouse Thread

51 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Why can structs not be null in C#?

Back to Forum: Coffeehouse
  • User profile image
    littleguru

    I got a question to you guys: Why can structs not be null in C#? I don't really understand it. Now they introduced the Nullable types with .NET 2.0, but I simply don't understand it.

    I understand that they haven't been in C, C++, etc. but isn't C# not a level higher then those languages? I mean a developer of C# doesn't care if the struct is managed on the stack and the other objects on the heap. Usually a C# developer has nothing to do with the program heap.

    This question leads me to another one: Are Nullable types only introduced since the guys at Microsoft couldn't change the behaviour of structs to be null? Is it only a plaster?

    Cheers
    Christian

    [edit]perhaps someone of the insiders could help me out (from MS) or anybody else who thinks to know an answer[/edit]

  • User profile image
    jonathanh

    A struct can't be null in the same way that an int can't be null, and a float can't be null - they're all value types (and really, a developer should care if they're on the stack rather than on the heap).

    Nullable types make dealing with SQL a lot easier...

  • User profile image
    littleguru

    I'm wondering why C# could not have abstracted that difference?

    I know that developer should care about if something is on the stack or not. But in C# you are not caring that much about the actual physical hardware that is behind the system.
    You are more focussing on the algorithm you want implement. You are a step higher then the hardware. You are developing in a virtual machine, but you don't even really care about it. You are no longer tied to the hardware. You can switch processor, your program has not to know, you can switch even OS, it does not really care your program.
    It's so different then programming in C or C++.

    Therefore I was asking myself, why the difference between structs and classes hasn't been removed... I mean: why should the developer care if a struct is managed on the stack? He/she is developing for the virtual machine... how the virtual machine does then the work is not so important for the dev.

    Christian

  • User profile image
    jonathanh

    If you fully abstract everything you end up with a scripting language, where you really have no idea how it does its magic or what it costs in terms of cycles or memory accesses.

    There are just too many cases where making something a struct rather than an object (or vice versa) will have a big effect on performance.

  • User profile image
    littleguru

    jonathanh wrote:
    If you fully abstract everything you end up with a scripting language, where you really have no idea how it does its magic or what it costs in terms of cycles or memory accesses.

    There are just too many cases where making something a struct rather than an object (or vice versa) will have a big effect on performance.


    I really understand that. Sometimes structs are a lot faster, that's true. I don't mean to remove them, but only to allow the developer to set them null.

    I was only wondering why this hasn't been implemented. .NET is a managed environment therefore the environment could handle the setting null for structs.

    Is there a reason, why it wasn't implemented? I was wondering if somebody said "no we don't do that" or if nobody thought to do it that way or if it was to complicated to do.

  • User profile image
    rhm

    There has to be a distinction between struct/value types that can be allocated on the stack and as parts of objects on the heap and the heap based objects/classes themselves. The reason is that for garbage collection and 'safe execution' to work it is important that references/pointers are only point to objects on the heap. If you were allowed to take a reference to a struct that was allocated on the stack and you then stored them inside some object on the heap and then the function returned what would the runtime do to that reference that's now in the heap somewhere? The posibilities for dealing with it safely are all too slow or completely impractical (go through the heap and null out invalid references; check all references to make sure they point to something valid before de-refing them). The only alternative would be to let people point to stuff on the stack without runtime checking like you can in regular C++, but then you have the risk that people leave dangling pointers to objects that no longer exist.

  • User profile image
    littleguru

    rhm wrote:
    There has to be a distinction between struct/value types that can be allocated on the stack and as parts of objects on the heap and the heap based objects/classes themselves. The reason is that for garbage collection and 'safe execution' to work it is important that references/pointers are only point to objects on the heap. If you were allowed to take a reference to a struct that was allocated on the stack and you then stored them inside some object on the heap and then the function returned what would the runtime do to that reference that's now in the heap somewhere? The posibilities for dealing with it safely are all too slow or completely impractical (go through the heap and null out invalid references; check all references to make sure they point to something valid before de-refing them). The only alternative would be to let people point to stuff on the stack without runtime checking like you can in regular C++, but then you have the risk that people leave dangling pointers to objects that no longer exist.



    Your ideas are also very true. But are you all not looking to much from a C, C++ developer view to the problem?

    As I said in the last post: isn't .NET not a managed environment?  It's all happening in a managed context. Nulling out the structure shouldn't be that complicated, or is it? That's what i'm wondering...

    [edit]

    re-read your posting. sorry my mother language isn't english... i see what you mean. but I'm still wondering. i mean: the structure could behave like it does right now, but only let the dev set it to null.

    The struct could stay on the heap, it mustn't be erased or removed somehow. It is then removed when the part of the heap is cleared. As it is right now.

    [/edit]

  • User profile image
    Minh

    jonathanh wrote:
    Nullable types make dealing with SQL a lot easier...


    Does Nullable types let you use your own class via the ? shortcut. Does it let me do something like:

    MyNullableType? toNullOrNotToNull;

  • User profile image
    Minh

    littleguru wrote:
    I'm wondering why C# could not have abstracted that difference?

    I'm guessing that at some point, you'd have to draw the line on the language design. Is nullable value types really worth it? Why not just use a class?

    littleguru wrote:

    Therefore I was asking myself, why the difference between structs and classes hasn't been removed...
    I mean: why should the developer care if a struct is managed on the stack?

    Because, there is a REAL, PRACTICAL performance difference between a class & a struct.

  • User profile image
    Maurits

    OK, but say you had a struct that was 30 bytes long (say)
    Couldn't a "NULL" for that struct be, by definition, 30 bytes of 0?

  • User profile image
    Sven Groot

    No, because a structure filled with zeros and a null reference are completely different things. On a conceptual level, null means "undefined value" while a struct with all zeros could very well be a legal value instance for that struct. On an implementation level, null means the reference doesn't point to anything. Since a struct is a value type, there is no reference and no pointing, so you can't point to nothing.

  • User profile image
    bitzero

    a) I'm fighting as hard as I can to get it so that CLASSES can't be assigned to null!!    Nulls are the single biggest cause of programming errors, and programmers are finally coming to the understanding that they are mostly unnecessary.   So, thank your lucky stars that structs AREN'T nullable - it's the only good reason to ever use them.

    b) C# 2005 comes with a nullable<> template which will allow you to explicitly declare something nullable, if you do want to go through that pain. 

    c)  you can't define a zero'd record as null - that's extraordinarily dangerous, because it might be quite validly zero.   A payment of $0.00 is quite different from "the payment hasn't been provided yet"

    d) we are abstracted from the hardware, and we are running on a virtual machine yes - that means that we don't need to understand the real hardware.  yes..     It doesn't mean that we can ignore what's happening in the virtual machine!   There is a fundamental difference between a struct and a class - and it's not just for your understanding of performance.  Compare for instance:
       class m {public int x;}
       struct n {public int x;}
      f( m v ) {v.x = 5;}   f ( n v ) {v.x = 5;}
      m a ; n b;  a.x = 10; b.x = 10; f(a); f(b); Print(a.x);Print(b.x);

    What's the difference?   It's a pretty important concept... structs and classes are very different things, and not interchangeable in the slightest.

    So - to sum up - if you WANT to assign a struct variable to null, then you are planning something very very wrong.













  • User profile image
    jonathanh

    Beer28 wrote:
    bitzero wrote: a) I'm fighting as hard as I can to get it so that CLASSES can't be assigned to null!!    Nulls are the single biggest cause of programming errors, and programmers are finally coming to the understanding that they are mostly unnecessary.   So, thank your lucky stars that structs AREN'T nullable - it's the only good reason to ever use them.


    au contraire, the whole point of nulling or zeroing out the first byte of a range of addressed memory(declare byte) is for YOUR, the programmer's benefit.

    You don't ever need to null or zero out that first byte of the multibyte addresses, zeroing it out is a tool or method programmers use to determine if the non-zero address at the first byte is either

    A. the start of valid data

    B. a junk address that happened to be there when the memory was allocated.

    null is a tool, for structs, classes and any allocated memory on the heap.

    The compiler doesn'T care if you never use null. It's all for your own benefit.

    I think you've confused yourself with all your talk of nulling out memory. That has no bearing on the topic. We're talking about the meaning of a "null struct", not a struct filled with nulls.

    Getting data values that are null (meaning "undefined") is common in certain fields, such as databases. That's what nullable means in this context - a data type that can represent valid value or null.

    And in that case 0 is most definitely not null

  • User profile image
    jonathanh

    Beer28 wrote:
    Setting a class or struct pointer to null doesn't fill a struct with zeros

    Ok, you got that bit mostly right. Of course, there's no such thing as a "struct pointer" in C#, but never mind...
    Beer28 wrote:

    saying
    obj foo = new obj;
    foo = NULL;

    is the same as saying

    obj foo = new obj;
    foo[0] = 0;

    Nope. Wrong. Not the same thing at all. Go take a course on pointers again!

  • User profile image
    jonathanh

    Great, you've written a C++ program. Now try to write it in C#, then explain why your two code fragments AREN'T the same, and you might yet pass the course...

  • User profile image
    jonathanh

    Beer28 wrote:
    I think it's pretty obvious that i was talking about object compiled code and not virtual IL compiled code.
    The only thing that's obvious is that you're trying to explain C# in terms of C++ and failing miserably.

    Beer28 wrote:
    Since C# doesn't really use pointers, and since you told me to go take a course on pointers, I'll assume that I have sufficiently demonstated that I need no course on pointers.
    Sure it uses pointers. What do you think a reference variable is?

    Beer28 wrote:
    EDIT: I did omit the * after obj* foo as a typo, I don't know if that made you think it was C#, though I don't code C#, and I had previously explained the same thing.
    Let's see, the thread is about C#, everyone else was referring to C#, and yet you post some code and expect us to understand that Angel it's actually C++ not C#, and (b) you really meant to include an extra pointer indirection?

    It's been a while since I taught undergrad programming, but I'd give that explanation a D...

  • User profile image
    jonathanh

    Beer28 wrote:
    I'd give your sunglasses an F
    Well sure, that's an undergrad picture of me in $5 knockoffs. Of course, as an undergrad I was also handing in problem sets where I used the right programming language, didn't make glaring mistakes in my code, and could actually explain the concept of NULL without inventing bizarre ideas about zero'ing out the first byte of an object. Does being a fat penguin compensate for the fact that you're 0 for 3?

  • User profile image
    jonathanh

    Beer28 wrote:
    The first byte, the first DWORD, it depends on the compiler, as long as the first object[0] = 0;

    That's what I meant.

    How is that a bizarre idea? That is a fact. That's what you're doing when you set something to null

    when you go

    *pseudocode*
    void* something = alloc(someN);
    something = NULL;

    whenever you use something, whether you allocated with new or an alloc function, that is an int containing the number which points to the address with the memory, that pointer is in fact something[0]

    It's an array of void which is a 32 bit type, or in the case of an object, it's the first 32 bits of that start address.
    Oh for crying out loud, you made the same mistake again.  If you want your code to match your text, you mean

    void* something = alloc(someN);
    *something = NULL; /* sets the first word of something to 0 */ 

    Beer28 wrote:
    The fact that they took that concept of null and applied it to scripting langauges and java and other languages as a manner of undefining an object, doesn't change that.
    Er, what? I think you've got your history confused here. 

    Beer28" wrote:
    And who really knows what's going on in the CLR when you set something to null?

    There is no way to dereference MSIL to asm. You guys never made that tool. There's no way to see under the hood.

    Ideally, you could view the memory and see if the first DWORD of the object is 0 in a memory viewer, but there is no memory viewer for the managed heap.

    Everything you describe in the context of the CLR is conceptual because it can't be verified as machine code. Not as far as I've been able to tell anyway.
    Riiiight, I've just beeen imagining all these years that the Visual Studio debugger lets me see what the actual x86 opcodes are. Yup, I hallucinated that, and the command-line tools. Oh, and that idea that I was actually inspecting the contents of objects in memory? Clearly I must have been mistaken, because we "never made that tool", and "there's no way to see under the hood", and "there's no viewer for the managed heap", and "it can't be verified as machine code". Because you said so. Riiiight. Oh wait, what's this here, do you say "Not as far as I've been able to tell anyway"? Why, yes you did. Does this mean that you're spouting your mouth off without actually checking your facts first? Why, I believe it does.

    You know the first thing to do when you find yourself in a deep hole? STOP DIGGING.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.