.net parameters



  • In .net you can pass function parameters by value and by reference as expected.  However, you also have to be aware of the object type.  There are value type and reference type objects.  If you pass a reference type object (classes, strings, pretty much any non-basic data type) by value what it is atually doing is passing a copy of the pointer that points to that variable.  This means that even if you pass a class by value, you can still modify the values of that object in the function and have those changes propagate back up.  Here's an MSDN article that talks a bit more about it http://msdn.microsoft.com/en-us/library/s6938f28.aspx.

    Coming from a C background this kinda freaked me out when I found out about it.  My co-workers flat out didn't believe when I first told them (they had been using .net for several years already).  Is this how other languages are moving to handling objects and parameters?

    I'm also not sure I understand the reasoning for doing it this way.  Is this to avoid always just passing large objects by reference to save on performance?



  • It's the same way it behaves in C++.  If you pass a pointer to an object, then act on that pointer, it will work with the object itself.  It makes a copy of the pointer, not the object.

    Addendum: Pretty sure it being this way has to do with the memory model and garbage collection.



  • Yes, I'm pretty sure this is why Object.clone() exists in Java, and I'm pretty sure there's a .NET equivalent.



  • @Sutherlands said:

    It's the same way it behaves in C++.  If you pass a pointer to an object, then act on that pointer, it will work with the object itself.  It makes a copy of the pointer, not the object.

    Addendum: Pretty sure it being this way has to do with the memory model and garbage collection.

    Yes, but I didn't create a pointer specifically.  I declared a class.  If I pass a class by value in C++ it will create a copy of that class and send that.  If I was declaring and passing pointers as you say then yes I would expect it to act exactly like this.  The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though.  You can't even declare pointers in vb.net



  • @Peraninth said:

    The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though.
    ... yes...

    You're comparing a managed memory language to an unmanaged memory language and complaining that they don't manage memory the same way?



  • @Peraninth said:

    Yes, but I didn't create a pointer specifically.  I declared a class.  If I pass a class by value in C++ it will create a copy of that class and send that.  If I was declaring and passing pointers as you say then yes I would expect it to act exactly like this.

    I suppose you can think of it as an "implicit" pointer declaration and dereferencing for class types. Interestingly enough, if you use a struct instead of a class, it will be passed by value.

    @Peraninth said:

      The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though

    This is absolutely correct. You can use pointers in C#, but you have to wrap them in an "unsafe" block, and I honestly don't know of any good reason to use them to begin with in C#...



  •  Your friends must be really shitty .NET programmers if they didn't know something this basic after years of practice.



  • @Sutherlands said:

    @Peraninth said:

    The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though.
    ... yes...

    You're comparing a managed memory language to an unmanaged memory language and complaining that they don't manage memory the same way?

    No, I'm commenting that C/C++ and .net don't handle parameters the same way.  When passing an object by value I would expect not to be able to change the value of that object and have those changes persist in the calling environment regardless of the memory management model used.  I wrongfully assumed it was one of those programming concepts that all languages would adhere to.

    What seems really weird, is that in a framework that tries to hide all the details of memory management and pointers you need to know if an object is a reference type or a value type. The MSDN article on passing parameters makes no mention of value type and reference type objects and how this can affect the behavior (the "for more information" links under the article totally dont count).  http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.100).aspx

    @ekolis said:

    Interestingly enough, if you use a struct instead of a class, it will be passed by value.

    Structs are value type objects in the .net world.



  • @Mona2000 said:

     Your friends must be really shitty .NET programmers if they didn't know something this basic after years of practice.

    I never claimed my co-workers were competent.  http://forums.thedailywtf.com/forums/t/25651.aspx

    Try harder.



  • @Peraninth said:

    No, I'm commenting that C/C++ and .net don't handle parameters the same way.  When passing an object by value I would expect not to be able to change the value of that object and have those changes persist in the calling environment regardless of the memory management model used.  I wrongfully assumed it was one of those programming concepts that all languages would adhere to.
    Well, they do behave the same, actually.  It's just that the object that you're passing by value is a reference (or pointer).  If you do

    void Func(Object o)

    {

       o = new Object();

    }

    That value will not be seen outside the function, because the pointer is still pointing to the previous object.  However, if you add ref, all of a sudden the value passed in... the reference/pointer... changes, and you will be able to get to the new object outside the function.@Peraninth said:

    What seems really weird, is that in a framework that tries to hide all the details of memory management and pointers you need to know if an object is a reference type or a value type.

    I don't think it's weird at all.@Peraninth said:
    The MSDN article on passing parameters makes no mention of value type and reference type objects and how this can affect the behavior (the "for more information" links under the article totally dont count). 
    See if you can find a picture of a random girl by using google (anything you find using the search function doesn't count).



  • @Peraninth said:

     The MSDN article on passing parameters makes no mention of value type and reference type objects and how this can affect the behavior (the "for more information" links under the article totally dont count).  http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.100).aspx 
    This makes even less sense when you consider that the links which you're saying don't count are sub-topics of the page that you're looking at.  How would you like them to document the behavior?



  • @Peraninth said:

    The MSDN article on passing parameters makes no mention of value type and reference type objects and how this can affect the behavior (the "for more information" links under the article totally dont count).  http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.100).aspx

    It doesn't have to. There is documentation on what a reference type and value type are, and there's documentation on how reference and value passing works. The only way to be surprised by the behavior of passing a reference type by value is to misunderstand what a reference type is.

    If you want to see some real fun with parameter passing, try this funky VB.Net behavior:


        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim x As Integer = 1
            TestPass((x))
            MessageBox.Show(x)
        End Sub
    
    Private Sub TestPass(ByRef x As Integer)
        x *= 2
    End Sub
    



        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim x As Integer = 1
            TestPass(x)
            MessageBox.Show(x)
        End Sub
    
    Private Sub TestPass(ByRef x As Integer)
        x *= 2
    End Sub
    


    The first snippet displays 1 and the second displays 2. C# is too strict to allow confusion like this to happen.



  • I've done non trivial coding in PHP, Java and C# and not once has this behaviour caused a problem. Quite the opposite in fact, I'd be inconvenienced if they started copying objects. In fact come to think of it PHP4 did it that way and it is one of the many reasons I'm glad it's dead.

    I remember the pass-by-value/pass-by-reference thing from my Java classes back in CompSci. Didn't you guys get that?

     



  • I vote this thread be renamed "The Pointer Semantics of Your World Frighten and Confuse Me!"



  • @Peraninth said:

    Yes, but I didn't create a pointer specifically.  I declared a class. 

    My favorite part of the thread. "I didn't raise my left hand, I lifted my not-right hand (of which I have two, just to thwart any pedantic dickweeds)."

    If you create an instance of a class in C#, then specifically creating a pointer is exactly what you have done.



  • This isn't new; doesn't every language that supports pass-by-reference semantics (which excludes java) do this?

    Passing an object by value pushes the pointer to the blob of memory where the object exists onto the stack, so the callee can change the state of the object in any way it wants, but it can't change the value of the pointer in the caller.  If passed by reference, then the stack gets a pointer to a pointer to the object, and you can change the pointed-to value (such as assigning a new object).

    For instance, I do something like this in VB6 (yes) all the time:

    Private Sub IterateInSomeUsefulWay(ByVal rst as ADODB.Recordset)

    Knowing full well that the current record is going to change in the process.



  • @Peraninth said:

    Coming from a C background this kinda freaked me out when I found out about it.  My co-workers flat out didn't believe when I first told them (they had been using .net for several years already).  Is this how other languages are moving to handling objects and parameters?

    In C or C++ you would be passing these objects by pointer all the time, in .Net it's implicit for anything declared class. In Java it goes even a bit further, because user types can only be declared class, since Java does not have struct.

    @Peraninth said:
    I'm also not sure I understand the reasoning for doing it this way.  Is this to avoid always just passing large objects by reference to save on performance?

    Polymorphic objects only ever make sense to be passed by pointer/reference. Since C# and Java are object-oriented languages with polymorphism as primary means of abstraction, they always pass objects by reference. The same is true for higher level languages. In dynamically typed language, everything is always polymorphic, so it must be passed by reference.

    Now in C/C++ you would actually pass by const pointer/reference when you don't want it modified. I do miss const a lot in C#, exactly for the reasons you mention. You can workaround by defining an interface that only contains the read access for the class, marking the class as implementing that interface and passing as that interface instead, but since that does not allow final method optimization, it would have some performance impact, though small, whereas const does not have any (it does not have benefit either, though, since const object can still be changed via other pointer, which is why D adds immutable).



  • @Bulb said:

    Polymorphic objects only ever make sense to be passed by pointer/reference. Since C# and Java are object-oriented languages with polymorphism as primary means of abstraction, they always pass objects by reference.


    I'm afraid I'm going to have to be pedantic here. There's a difference between passing objects by reference and passing references to objects by value.



  • @CarnivorousHippie said:

    This isn't new; doesn't every language that supports pass-by-reference semantics (which excludes java) do this?

    Passing an object by value pushes the pointer to the blob of memory where the object exists onto the stack, so the callee can change the state of the object in any way it wants, but it can't change the value of the pointer in the caller.  If passed by reference, then the stack gets a pointer to a pointer to the object, and you can change the pointed-to value (such as assigning a new object).

    No. Consider the following code in C (also valid in C++):

    struct foo
    {
      int x;
    };
    

    void func(foo f)
    {
    /* func gets its own copy of the struct */
    f.x = 42;
    }

    void main()
    {
    struct foo f;
    f.x = 1;
    func(f);
    /* f.x is still 1 here */
    }

    The main WTF in the OP seems to be that C# uses the same syntax for declaring different things; bar b; may get you a stack object or a pointer, depending on what bar is. As a consequence, it's not clear (from the syntax) exactly what is being passed by value. This is probably not confusing for someone who has used C# for years, but for someone with a C or C++ background it is.

    Disclaimer: I haven't actually written a single line of C# code, I'm just using information others have posted here.



  • @Peraninth said:

    Yes, but I didn't create a pointer specifically.  I declared a class.  If I pass a class by value in C++ it will create a copy of that class and send that.  If I was declaring and passing pointers as you say then yes I would expect it to act exactly like this.  The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though.  You can't even declare pointers in vb.net

     

    did you declare a class or a variable that was of the class type? declaring a class would simply be defining it.

    Also, recall that in C++ new returns a pointer to the object it constructs. Java and C# both use new so it makes sense that the result would be a reference. Also, recall that Any variable that can point to an object can also be null, which is also only possible with Pointers.



  • @lettucemode said:

    @Peraninth said:

    Yes, but I didn't create a pointer specifically.  I declared a class. 

    My favorite part of the thread. "I didn't raise my left hand, I lifted my not-right hand (of which I have two, just to thwart any pedantic dickweeds)."

    If you create an instance of a class in C#, then specifically creating a pointer is exactly what you have done.

    Wow this thread is depressing.  If you think the two things below (C#) are the same thing, then you are sadly misinformed.

    char* p;  //look at me I'm an honest to god pointer!
    string pp;  //sorry guys, i'm just a reference type object

    If you are still having a hard time swallowing this go read: http://blogs.msdn.com/b/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx



  • @Peraninth said:

    Yes, but I didn't create a pointer specifically.  I declared a class.  If I pass a class by value in C++ it will create a copy of that class and send that.  If I was declaring and passing pointers as you say then yes I would expect it to act exactly like this.  The .net framework seems to go out of its way to hide pointers and memory management from the programmers, though.  You can't even declare pointers in vb.net

    You declared a reference to an object that's in the heap. In .NET, references are type-safe pointers. So there.



  • @Peraninth said:


    Wow this thread is depressing.  If you think the two things below (C#) are the same thing, then you are sadly misinformed.

    char* p;  //look at me I'm an honest to god pointer!
    string pp;  //sorry guys, i'm just a reference type object

    If you are still having a hard time swallowing this go read: http://blogs.msdn.com/b/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx

    I don't think that anyone is really saying what you allege. It's true, as your link points out, that talking about an address is an implementation detail, but the reference is still using a pointer (even if we change them to be not addresses, but an opaque handle, as Lippert says).

    I haven't used C# in several years, and I've never really used VB.NET, so I can't add much there, but the explanation as it applies to java seems to apply here. When you pass a .Net reference type object, you're passing a pointer by value. That's probably wrong in a pedantically dickweed sort of way, but it's probably right from an actual implementation sort of way. IOW, your local variable, which you pass as a parameter, is really a pointer to an object. When you pass it, the method can do stuff to the data pointed to by your parameter. But it won't change the value of the variable in the calling method (i.e., what that's pointing to).

    Of course, .Net gives you a way to pass a pointer to a copy of your object, which seems like the main difference here.



  • @BC_Programmer said:

     Also, recall that Any variable that can point to an object can also be null, which is also only possible with Pointers.

     The amount of wrong in this thread is terrifying.

    http://msdn.microsoft.com/en-us/library/3ewxz6et.aspx

    "Value types are also nullable, which means they can store an additional non-value state."

    Unless we're now saying that value type objects are also the exact same thing as pointers?



  • <sarcasm> And this is why you should just make all your variables public globals that way you do not have to pass them into any function.</sarcasm>



  • @Peraninth said:

    http://msdn.microsoft.com/en-us/library/3ewxz6et.aspx

    "Value types are also nullable, which means they can store an additional non-value state."

    Unless we're now saying that value type objects are also the exact same thing as pointers?

    That's a bit misleading. If you click the Value types link near the top of that page, it says: "Unlike reference types, a value type cannot contain the null value. However, the nullable types feature does allow for values types to be assigned to null." So plain value types themselves can't be null, but you can make nullable types based on them (int? is shorthand for Nullable<int>, which is different from int even though it's largely interchangeable). Internally, this could be implemented as either a pointer or a value and a flag.



  • @tdb said:

    @Peraninth said:

    http://msdn.microsoft.com/en-us/library/3ewxz6et.aspx

    "Value types are also nullable, which means they can store an additional non-value state."

    Unless we're now saying that value type objects are also the exact same thing as pointers?

    That's a bit misleading.

    I'd say it's not misleading, but plain wrong. Value types are not, in general, nullable.



  • @Sutherlands said:

    @Peraninth said:
     The MSDN article on passing parameters makes no mention of value type and reference type objects and how this can affect the behavior (the "for more information" links under the article totally dont count).  http://msdn.microsoft.com/en-us/library/0f66670z(v=vs.100).aspx 
    This makes even less sense when you consider that the links which you're saying don't count are sub-topics of the page that you're looking at.  How would you like them to document the behavior?

    Ok, seriously.  Read that article.  Now on that same page click on other versions and select .net 2003.  You tell me which one is more clear about the fact that the type of the object affects what actually happens.  I wasn't trying to say the documentation didn't exist anywhere just that it is poor (what's terrible is that the newer version is the worse one).

    @tdb said:


    No. Consider the following code in C (also valid in C++):
     struct foo
    {
      int x;
    };

    void func(foo f)
    {
      /* func gets its own copy of the struct /
      f.x = 42;
    }

    void main()
    {
      struct foo f;
      f.x = 1;
      func(f);
      /
    f.x is still 1 here */
    }
     
    The main WTF in the OP seems to be that C# uses the same syntax for declaring different things; bar b; may get you a stack object or a pointer, depending on what bar is. As a consequence, it's not clear (from the syntax) exactly what is being passed by value. This is probably not confusing for someone who has used C# for years, but for someone with a C or C++ background it is.
     
    Disclaimer: I haven't actually written a single line of C# code, I'm just using information others have posted here.

    Here's a rough equivalent in C#:

    public class temp
    {
      public int x;
    }

    public void Foo(temp thing)
    {
      thing.x = 24;
    }

    public void OtherFoo()
    {
      temp stuff = new temp();
      stuff.x = 6;
      Foo(stuff);
      //stuff.x == 24
    }

    If you change "public class temp" to "public struct temp" and nothing else, the value after calling Foo will be 6.  Would you, tdb, after reading the link above expect this behavior?  I call bullshit on anyone who says this behavior wouldn't completely surprise them coming from a C/C++ background.

    @boomzilla said:

    I don't think that anyone is really saying what you allege. It's true, as your link points out, that talking about an address is an implementation detail, but the reference is still using a pointer (even if we change them to be not addresses, but an opaque handle, as Lippert says).

    The point I was trying to make is that reference type objects are still objects.  They are implemented using pointers.  I never said I didn't understand this (thanks though for the 15 people who felt the need to try and explain).  I never even said this was bad or wrong.  What doesn't make sense to me is why the .net framework goes out of its way to hide/discourage pointers and memory manipulation (value type objects and reference type objects dont look any different in code right?) but then can't quite handle passing reference type objects by value.  I work in a vb.net shop and I can tell you that almost none of my co-workers know anything about reference type objects let alone pointers.  It seems like the .net developers are OK with this but that lack of knowledge could easily lead to bugs when passing reference types by value.  Like I said in my first post, they had been programming in vb.net for years and had no idea about this behavior.



  • Maybe you should be programming in C++/CLI.  I'm sure then things would become crystal clear for you.



  • @Peraninth said:

    The point I was trying to make is that reference type objects are still objects.  They are implemented using pointers.  I never said I didn't understand this (thanks though for the 15 people who felt the need to try and explain). 

    They felt the need to explain because you seemed confused as to why two different references to the same object can both change said object's state. 



  • @Peraninth said:

    It seems like the .net developers are OK with this but that lack of knowledge could easily lead to bugs when passing reference types by value. Like I said in my first post, they had been programming in vb.net for years and had no idea about this behavior.

    So... it's a non-issue.



  • @Peraninth said:

    If you change "public class temp" to "public struct temp" and nothing else, the value after calling Foo will be 6.  Would you, tdb, after reading the link above expect this behavior?  I call bullshit on anyone who says this behavior wouldn't completely surprise them coming from a C/C++ background.

    Not sure what you're getting at here? I did say the C# behavior is confusing for someone with a C/C++ background (like me). My post was offering a counterexample to CarnivorousHippie's claim that all languages would treat pass-by-value the same way as C#. It was also trying to explain to others that the major source of the confusion is that the same syntax can result in different behavior depending on which kind of type it is.



  • Well, I'm not familiar with C#, but in Java there is no pass-by-reference. Everything is pass-by-value, it's just that the only value types are

    1. byte
    2. short
    3. char
    4. int
    5. long
    6. float
    7. double
    8. void* (with type checking)

     

    Once you get that, there's nothing to confuse any more. Saying "ThreadPoolFactoryService tpfs = ..." simply declares a variable holding a pointer to ram containing data for an object of type ThreadPoolFactoryService. You can NEVER get the location of that pointer in memory, though. That is, you can't write a function which will take a (in C terms) void**. You can't write a function which will change the address at which "tpfs" points. It is impossible to get the address of a variable. Everything that deals with an object returns or gets a pointer to type-checked ram.

    It seems that C# extends it wih a few more types past byte,short,etc. that aren't pointers but that shouldn't confuse you - basically there are types which are a chunk of data and types which are a type-checked void*. And you can't interchange the two. And you can never take the address of a variable in safe code. And everything is pass-by-value.



  • Your co-workers clearly didn't RTFM, though you did, congrats!  Ask them what happens when you pass a reference type (object) by ref. 

    This is a good .net question:

    class Foo { public int SomeVal; }

    static void Main(int[] args)

    {

       var foo = new Foo() { SomeVal = 1 };

       DoStuff(foo); 

       // What is the value of foo.SomeVal ?

       DoStuff(ref foo);

       // What about now?

    }

    static void DoStuff(ref Foo myFoo)

    {

      myFoo = new Foo() { SomeVal = 100 };

    }

    static void DoStuff(Foo myFoo)

    {

       myFoo = new Foo() { SomeVal }; 

    }



  • @tdb said:

    @CarnivorousHippie said:

    This isn't new; doesn't every language that supports pass-by-reference semantics (which excludes java) do this?

    Passing an object by value pushes the pointer to the blob of memory where the object exists onto the stack, so the callee can change the state of the object in any way it wants, but it can't change the value of the pointer in the caller.  If passed by reference, then the stack gets a pointer to a pointer to the object, and you can change the pointed-to value (such as assigning a new object).

    No. Consider the following code in C (also valid in C++):

    struct foo
    {
      int x;
    };
    

    void func(foo f)
    {
    /* func gets its own copy of the struct */
    f.x = 42;
    }

    void main()
    {
    struct foo f;
    f.x = 1;
    func(f);
    /* f.x is still 1 here */
    }

    The main WTF in the OP seems to be that C# uses the same syntax for declaring different things; bar b; may get you a stack object or a pointer, depending on what bar is. As a consequence, it's not clear (from the syntax) exactly what is being passed by value. This is probably not confusing for someone who has used C# for years, but for someone with a C or C++ background it is.

    Disclaimer: I haven't actually written a single line of C# code, I'm just using information others have posted here.

    I should have used "reference type" instead of "object".  As I've termed things, struct != object.  Passing a struct (by value) pushes a copy of the struct on the stack, just like passing 3 by value pushes a copy of 3 on the stack.

    Can't say I have a C background, unless you count college (I haven't touched C since 93), but even then I had no confusion about by-val/by-ref; must have been the semester of assembly.



  • @Mo6eB said:

    It seems that C# extends it wih a few more types past byte,short,etc. that aren't pointers but that shouldn't confuse you - basically there are types which are a chunk of data and types which are a type-checked void*. And you can't interchange the two. And you can never take the address of a variable in safe code. And everything is pass-by-value.

    C#'s value types include anything declared as a struct (as opposed to class), so I'd say it's more than a few. And the syntax for declaring variables of struct and class types is identical, but they behave differently, so if confronted with unfamiliar code you'll have to locate the type declaration to figure out what's happening.

    There seems to be a better term to describe what Java and C# mean by "pass-by-value": pass-by-sharing (for C# this applies only to reference types, not value types). The caller is sharing the object with the callee, so changes to that object can be made, but it can't be replaced with another object.



  • @Peraninth said:

    Ok, seriously.  Read that article.  Now on that same page click on other versions and select .net 2003.  You tell me which one is more clear about the fact that the type of the object affects what actually happens.  I wasn't trying to say the documentation didn't exist anywhere just that it is poor (what's terrible is that the newer version is the worse one).

    Click the link.  Look to the left.  Now back at me.  Now back to the left.  Do you see where "Passing parameters" is orange?  Do you see where it has sub-topics called "Passing Value-Type Parameters" and "Passing Reference-Type Parameters"?  I'm sorry if it's not clear to you, but it's probably clearer to more people than it's less clear to.@Peraninth said:

    If you change "public class temp" to "public struct temp" and nothing else, the value after calling Foo will be 6.  Would you, tdb, after reading the link above expect this behavior?  I call bullshit on anyone who says this behavior wouldn't completely surprise them coming from a C/C++ background.

    Say what you want.  I came to C# from a C++ background and it didn't surprise me.  (I've also worked in Java, but it didn't surprise me then, either.)@Peraninth said:
    What doesn't make sense to me is why the .net framework goes out of its way to hide/discourage pointers
    Because they are UNSAFE TO USE and cause lots of bugs.@Peraninth said:
    and memory manipulation
    because it's UNSAFE TO USE and causes lots of bugs.@Peraninth said:
     but then can't quite handle passing reference type objects by value.
    They are.  I'm sorry you can't see that.@Peraninth said:
    I work in a vb.net shop and I can tell you that almost none of my co-workers know anything about reference type objects let alone pointers. 
    I would never hire one of your coworkers.  But then you probably wouldn't either, judging by your previous sidebar topic.  You seem like you read Eric Lippert, or at least can find answers to stuff by googling.  You might do ok.  If they've been working in .Net for awhile and don't even know the only difference between structs and classes, they aren't going anywhere in the world.



  • @CarnivorousHippie said:

    I should have used "reference type" instead of "object".  As I've termed things, struct != object.  Passing a struct (by value) pushes a copy of the struct on the stack, just like passing 3 by value pushes a copy of 3 on the stack.

    Can't say I have a C background, unless you count college (I haven't touched C since 93), but even then I had no confusion about by-val/by-ref; must have been the semester of assembly.

    Well, in C++ there's very little difference between struct and class; in fact the only difference is the default protection of members and base classes (for structs it's public, for classes it's private). If you replace the struct keyword from my code with class and make the member explicitly public, it'll behave in the exact same way under C++ semantics, while C# semantics would have the value in main change.



  • @tdb said:

    @Peraninth said:

    If you change "public class temp" to "public struct temp" and nothing else, the value after calling Foo will be 6.  Would you, tdb, after reading the link above expect this behavior?  I call bullshit on anyone who says this behavior wouldn't completely surprise them coming from a C/C++ background.

    Not sure what you're getting at here? I did say the C# behavior is confusing for someone with a C/C++ background (like me). My post was offering a counterexample to CarnivorousHippie's claim that all languages would treat pass-by-value the same way as C#. It was also trying to explain to others that the major source of the confusion is that the same syntax can result in different behavior depending on which kind of type it is.

    Disclaimer:  My claim is not based on experience or even familiarity with all languages, but just on the definition on passing by val/ref. YMMV.



  •  @Jaime said:

    It doesn't have to. There is documentation on what a reference type and value type are, and there's documentation on how reference and value passing works. The only way to be surprised by the behavior of passing a reference type by value is to misunderstand what a reference type is.

    If you want to see some real fun with parameter passing, try this funky VB.Net behavior:


        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim x As Integer = 1
            TestPass((x))
            MessageBox.Show(x)
        End Sub
    
    Private Sub TestPass(ByRef x As Integer)
        x *= 2
    End Sub
    

    ...

     You think that is funky, you don't even need to define the parameters to event handlers anymore:

    Private Sub Button1_Click() Handles Button1.Click
        ...
    End Sub

     

    :)

     



  • @Sutherlands said:

    @Peraninth said:
    What doesn't make sense to me is why the .net framework goes out of its way to hide/discourage pointers
    Because they are UNSAFE TO USE and cause lots of bugs.@Peraninth said:
    and memory manipulation
    because it's UNSAFE TO USE and causes lots of bugs.

    They're unsafe to use in the exact same way a chainsaw is unsafe to use. You can hurt yourself badly with them, but in skilled hands they are powerful tools. There are lots of bugs even without direct access to memory management, and in many cases an algorithm bug is harder to track down than a simple memory access violation. (There are tools for the latter, but the former still relies on a human analyzing the code.)

    @Sutherlands said:

    @Peraninth said:
     but then can't quite handle passing reference type objects by value.
    They are.  I'm sorry you can't see that.

    The problematic thing here is defining what actually is a value. A collection of simple values (i.e. a struct) is evidently a value. However, if you decorate it with the word class instead of struct, it ceases to be a value and instead you have a reference to that collection which is a value. Things get even more confusing if you have a struct containing a reference to a class. This is why C++ provides the const keyword (and the rarely used mutable) on both variables and methods to indicate what can and can't be modified.



  • @Mythran said:

     @Jaime said:

    It doesn't have to. There is documentation on what a reference type and value type are, and there's documentation on how reference and value passing works. The only way to be surprised by the behavior of passing a reference type by value is to misunderstand what a reference type is.

    If you want to see some real fun with parameter passing, try this funky VB.Net behavior:


        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim x As Integer = 1
            TestPass((x))
            MessageBox.Show(x)
        End Sub
    
    Private Sub TestPass(ByRef x As Integer)
        x *= 2
    End Sub
    

    ...

     You think that is funky, you don't even need to define the parameters to event handlers anymore:

    Private Sub Button1_Click() Handles Button1.Click
        ...
    End Sub

    :)

    Oh good god, tell me you're joking...  Who the fuck is steering the VB.net language design team at MS?



  • @tdb said:

    They're unsafe to use in the exact same way a chainsaw is unsafe to use. You can hurt yourself badly with them, but in skilled hands they are powerful tools. There are lots of bugs even without direct access to memory management, and in many cases an algorithm bug is harder to track down than a simple memory access violation. (There are tools for the latter, but the former still relies on a human analyzing the code.)

    A memory leak is not easy to track down.  Pointers are simply unnecessary.  C# has a way to use them, but in all the time I've been writing C#, not once have a said to myself "I really need to use pointers here."  Even in skilled hands they still create bugs that simply wouldn't have happened in C#, which is why they make you write "unsafe" around the portion in order to use them at all.  Regardless of whether they are low-hanging fruit, I can get rid of entire classes of bugs by using C#.  That's a win to me.@tdb said:
    The problematic thing here is defining what actually is a value. A collection of simple values (i.e. a struct) is evidently a value. However, if you decorate it with the word class instead of struct, it ceases to be a value and instead you have a reference to that collection which is a value. Things get even more confusing if you have a struct containing a reference to a class.
    I don't get what the difficulty is.  It's all pretty well explained here: http://msdn.microsoft.com/en-us/library/ms173109.aspx

    @tdb said:

    This is why C++ provides the const keyword (and the rarely used mutable) on both variables and methods to indicate what can and can't be modified.
    Const is one thing I wish C# had.



  • Yeah, that's pretty much to be expected, especially when you understand the history of .NET.

    Back in the late 90s, when Microsoft realized that Java wasn't going away and they had nothing that had any chance of competing with it, they did what they've always done best: find the best thing out there among the competition, blatantly rip it off, and Microsoft-ize it.  The best thing out there was Delphi, and this time they were particularly egregious in their application of the standard strategy: instead of simply making their own Delphi clone they actually hired away Anders Hejlsberg, the creator of Delphi, and other Delphi team members from Borland to make it for them.  This got them in a lot of legal trouble, but being Microsoft, they bought their way out of it. So what they ended up with was a product that resembles nothing so much as Delphi rewritten to feel like Java.  (It's evolved a bit since then, but it's pretty blatant in the earlier versions of C# and .NET if you know what you're looking at.)

    And how is this little history lession relevant to the topic at hand?  Because the value-type/reference-type and parameter passing semantics you described are exactly how Delphi does it.



  • @Sutherlands said:

    Const is one thing I wish C# had.

    Ask and you shall receive

    WTF is wrong with this thread?



  • @serguey123 said:

    @Sutherlands said:

    Const is one thing I wish C# had.

    Ask and you shall receive

    WTF is wrong with this thread?

    Const on a method parameter, you numbnuts.


  • @C-Octothorpe said:

    Oh good god, tell me you're joking...  Who the fuck is steering the VB.net language design team at MS?

    Wait, what's the problem? To me that's like int main(int argc, char** argv); vs. int main(void); - if you don't plan on using the parameters you can omit them.

     



  • @Sutherlands said:

    @tdb said:

    They're unsafe to use in the exact same way a chainsaw is unsafe to use. You can hurt yourself badly with them, but in skilled hands they are powerful tools. There are lots of bugs even without direct access to memory management, and in many cases an algorithm bug is harder to track down than a simple memory access violation. (There are tools for the latter, but the former still relies on a human analyzing the code.)

    A memory leak is not easy to track down.

    Have you ever used valgrind? It can give a very nice summary of leaked memory at the end, right down to where each piece of memory was allocated and what the call stack looked like when it was allocated. It can't catch cases where object accumulate in a list somewhere when they shouldn't and are freed (through normal memory management procedures) when the program terminates, but then again neither can a garbage collector (because the list is live). It's also somewhat hampered by certain libraries not bothering to free some of their memory "because it gets freed anyway when the process dies", so sometimes you have to filter through lots of spam.

    @Sutherlands said:
    Pointers are simply unnecessary.  C# has a way to use them, but in all the time I've been writing C#, not once have a said to myself "I really need to use pointers here."

    I'd love to see you write an implementation of the CLR without using pointers. Or any self-bootstrapping language. Or an OS.

    @Sutherlands said:
    Even in skilled hands they still create bugs that simply wouldn't have happened in C#, which is why they make you write "unsafe" around the portion in order to use them at all.  Regardless of whether they are low-hanging fruit, I can get rid of entire classes of bugs by using C#.  That's a win to me.

    Perhaps I'm just getting old, but I see all kinds of automatic memory management as part of the "everyone can program" fad that's been going on for a decade or so (there were some attempts even earlier but they never caught much wind). The danger here is that as programming is dumbed down, dumber people are going to pick it up, and managers are too dumb to see the difference so the dumb people get hired and write dumb code. If programming had remained hard, we might have less different applications, but the existing ones would be of higher quality.

    @Sutherlands said:
    @tdb said:
    The problematic thing here is defining what actually is a value. A collection of simple values (i.e. a struct) is evidently a value. However, if you decorate it with the word class instead of struct, it ceases to be a value and instead you have a reference to that collection which is a value. Things get even more confusing if you have a struct containing a reference to a class.
    I don't get what the difficulty is.  It's all pretty well explained here: http://msdn.microsoft.com/en-us/library/ms173109.aspx

    Well explained != intuitive



  • @heterodox said:

    @C-Octothorpe said:

    Oh good god, tell me you're joking...  Who the fuck is steering the VB.net language design team at MS?

    Wait, what's the problem? To me that's like int main(int argc, char** argv); vs. int main(void); - if you don't plan on using the parameters you can omit them.

    I think C-Octothorpe, like me, saw an implication that you could access those parameters even though they are not declared. I don't know if this is the case and don't care enough to find out, so perhaps one of the VB coders here will tell us.



  • @tdb said:

    Have you ever used valgrind?
    Did I say it was impossible to track down memory leaks?  No.  It's not easy.  And it's certainly not as easy as not having any in the first place.@tdb said:

    I'd love to see you write an implementation of the CLR without using pointers. Or any self-bootstrapping language. Or an OS.

    You want me to write an OS in .Net?  I'm sure you had a point here, but I'm not sure what it was...@tdb said:

    Perhaps I'm just getting old, but I see all kinds of automatic memory management as part of the "everyone can program" fad that's been going on for a decade or so (there were some attempts even earlier but they never caught much wind). The danger here is that as programming is dumbed down, dumber people are going to pick it up, and managers are too dumb to see the difference so the dumb people get hired and write dumb code. If programming had remained hard, we might have less different applications, but the existing ones would be of higher quality.

    It makes it easier for dumb people to program, but it also makes it easier for smart people to program.  If you have a manager that can't tell the difference between candidates in C#, they weren't going to be able to tell the difference between candidates in C++ either.  Most tasks can be completed faster in C# than in C++.  The quality of existing programs is going to be higher, in fact, because the quality of candidates is the same in either language, but it's easier to write a good program in C#.


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.