locked
Request Feature : Can we have feature return struct by reference? RRS feed

  • Question

  • class A
    {
        Matrix[] AllMatrix;
        Dictionary<string,int> IndexLookUp;
        public ref Matrix GetMatrix(string name)
        {
            int index = IndexLookUp[name];
            return ref AllMatrix[index];
        }
    }
    
    
    class Program
    {
        public static void Main()
        {
            A a = new A();
    
            a.GetMatrix("RedTrain").Translation = new Vector3(0,0,20);
        }
    }

    Something like this is useful in many situation. Especially optimization by encapsulation. This code is safer than return pointer directly

    Wednesday, February 22, 2012 11:37 AM

Answers

  • Ah of course. :)

    There is some discussion about it here:

    http://stackoverflow.com/questions/4542536/is-it-possible-to-return-a-reference-to-a-variable-in-c

    And a very good discussion here:

    http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals.aspx

    If you want to make an official request for this feature, the best place to do so is:

    https://connect.microsoft.com/VisualStudio/feedback


    • Edited by Matthew Watson Wednesday, February 22, 2012 1:56 PM
    • Proposed as answer by Patrice ScribeMVP Thursday, February 23, 2012 12:35 PM
    • Marked as answer by Thaina Friday, February 24, 2012 10:50 AM
    Wednesday, February 22, 2012 1:41 PM
  • As for why this feature doesn't exist in the language, that's fairly simple.  If you create a struct in a method and attempt to return it via a ref call then, either explicitly or implicitly, it will need to be boxed.  If it wasn't then the variable leaves scope as soon as the method ends so you now have a reference to an invalid location in memory (unless the compiler moves the struct to the heap and gives a reference to that, which is basically the definition of boxing).  In your case, you are returning a reference to an instance variable, not a local one, but it's still possible for that instance variable to go out of scope if these types of returning by reference calls were allowed.

    In fact doing this is possible in C/C++, and when done can be rather nasty.  Here is a link to a good explination about what can make this such a nasty bug and why Eric and the other C# designers ensured that it's a mistake that can't be made in .NET.

    Check out this blog by Eric Lippert. He explains how he already created a test version of the compiler that supports this feature. He also explains that it is possible for the compiler to detect and outlaw the practice returning refs to stack-based items.

    The main reason they haven't implemented this feature isn't technical - it's due to time constraints, and the fact that there is no really compelling case to add this to the language.

    • Marked as answer by Thaina Friday, February 24, 2012 10:46 AM
    Friday, February 24, 2012 10:24 AM

All replies

  • Where is the structure in your example? I see only a class.
    Wednesday, February 22, 2012 1:25 PM
  • Matrix is struct, in XNA, or even in System.Drawing
    Wednesday, February 22, 2012 1:26 PM
  • Ah of course. :)

    There is some discussion about it here:

    http://stackoverflow.com/questions/4542536/is-it-possible-to-return-a-reference-to-a-variable-in-c

    And a very good discussion here:

    http://blogs.msdn.com/b/ericlippert/archive/2011/06/23/ref-returns-and-ref-locals.aspx

    If you want to make an official request for this feature, the best place to do so is:

    https://connect.microsoft.com/VisualStudio/feedback


    • Edited by Matthew Watson Wednesday, February 22, 2012 1:56 PM
    • Proposed as answer by Patrice ScribeMVP Thursday, February 23, 2012 12:35 PM
    • Marked as answer by Thaina Friday, February 24, 2012 10:50 AM
    Wednesday, February 22, 2012 1:41 PM
  • You can always box the struct if you need to treat it as a reference...
    Wednesday, February 22, 2012 3:12 PM
  • This is for performance reason
    Thursday, February 23, 2012 6:55 AM
  • This is for performance reason

    If the struct is sufficently small then copying it when it is returned will not be significantly slower than copying a reference to it.  If it's large you can make a wrapper class to hold onto it (basically manual boxing).  If you're only ever copying it in the one place, then yes, boxing of any sort would be a net loss, but if it would be copied quite a bit then boxing/unboxing once may end up being faster than a dozen copies moving the struct around.

    If you really, really want to just return the object in the one place by reference, then just use a ref/out parameter with a void method rather than returning the struct.

    Thursday, February 23, 2012 3:09 PM
  • As for why this feature doesn't exist in the language, that's fairly simple.  If you create a struct in a method and attempt to return it via a ref call then, either explicitly or implicitly, it will need to be boxed.  If it wasn't then the variable leaves scope as soon as the method ends so you now have a reference to an invalid location in memory (unless the compiler moves the struct to the heap and gives a reference to that, which is basically the definition of boxing).  In your case, you are returning a reference to an instance variable, not a local one, but it's still possible for that instance variable to go out of scope if these types of returning by reference calls were allowed.

    In fact doing this is possible in C/C++, and when done can be rather nasty.  Here is a link to a good explination about what can make this such a nasty bug and why Eric and the other C# designers ensured that it's a mistake that can't be made in .NET.

    Thursday, February 23, 2012 4:18 PM

  •     class A
        {
            Matrix[] AllMatrix;
            Dictionary<string, int> IndexLookUp;
            public void GetMatrix(string name, ref Matrix matrix)
            {
                int index = IndexLookUp[name];
                matrix = AllMatrix[index];
            }
    
        }
    
        public struct Matrix
        {
            public int X;
            public int Y;
        }
    
        class Program
        {
            public static void Main()
            {
                A a = new A();
                //a.GetMatrix("RedTrain").Translation = new Vector3(0, 0, 20);
                Matrix matrix = new Matrix();
                a.GetMatrix("RedTrain", ref matrix);
            }
        }

    Why don't you just use the 'ref' or 'out' keywords in the method signature?

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://thesharpercoder.blogspot.com/



    Thursday, February 23, 2012 11:43 PM
    Moderator
  • As for why this feature doesn't exist in the language, that's fairly simple.  If you create a struct in a method and attempt to return it via a ref call then, either explicitly or implicitly, it will need to be boxed.  If it wasn't then the variable leaves scope as soon as the method ends so you now have a reference to an invalid location in memory (unless the compiler moves the struct to the heap and gives a reference to that, which is basically the definition of boxing).  In your case, you are returning a reference to an instance variable, not a local one, but it's still possible for that instance variable to go out of scope if these types of returning by reference calls were allowed.

    In fact doing this is possible in C/C++, and when done can be rather nasty.  Here is a link to a good explination about what can make this such a nasty bug and why Eric and the other C# designers ensured that it's a mistake that can't be made in .NET.

    Check out this blog by Eric Lippert. He explains how he already created a test version of the compiler that supports this feature. He also explains that it is possible for the compiler to detect and outlaw the practice returning refs to stack-based items.

    The main reason they haven't implemented this feature isn't technical - it's due to time constraints, and the fact that there is no really compelling case to add this to the language.

    • Marked as answer by Thaina Friday, February 24, 2012 10:46 AM
    Friday, February 24, 2012 10:24 AM
  • I already know things you talk about. But in the end using big struct is another coding style for performance reason. Using class always affect performance even 100 years later compare to use struct, because GC still need to do complicate work. struct, on the other hand, don't make GC do anything

    In many time we don't need to copy struct. We want to manage a bulk of large memory in safer way than pointer and that's all. Using class ruin it all with garbage collector. And copy memory larger than 32 byte is slower than reference. And scatter memory is drop some performance too

    I'm really bored from some random guy think he is a priest of C# and quote the word "You should not use struct too big, change it to class". Please stop, I know, you never think outside their box

    Just add some feature like this than C# speed can boost to equal C++ but people like you try to be a hindrance to us who need performance in a C# world. That's sucks

    Friday, February 24, 2012 10:45 AM
  • Because you don't understand the use case of my feature

    You just confuse how to use this feature and just think you know everything so you try to tell me another nonsense out of my point

    • Edited by Thaina Friday, February 24, 2012 10:50 AM
    Friday, February 24, 2012 10:47 AM
  • Yes I too, remember there are already someone in Microsoft try to add this feature. But it so old and I don't remember where. So I try to find a way to tell Microsoft that there are people still want this feature
    • Edited by Thaina Friday, February 24, 2012 10:54 AM
    Friday, February 24, 2012 10:53 AM
  • I already know things you talk about. But in the end using big struct is another coding style for performance reason. Using class always affect performance even 100 years later compare to use struct, because GC still need to do complicate work. struct, on the other hand, don't make GC do anything

    Now that's just not true. Structs don't always add work for the GC the way classes do, but that doesn't mean that they never do. Structs can have performance advantages when used properly, and they can negatively impact performance when used improperly.

    In many time we don't need to copy struct. We want to manage a bulk of large memory in safer way than pointer and that's all. Using class ruin it all with garbage collector. And copy memory larger than 32 byte is slower than reference. And scatter memory is drop some performance too

    I have no idea what you're trying to say here. How are classes any less 'safe' than structs. If this was c++ and you had to manage the heap memory yourself I'd give it some thought, but C# manages all of that for you. I have never even heard or problems related to what you're talking about. As for copying large amounts of memory, how does that add to your argument? As for fragmenting memory, I don't see how anything I suggested here would involve doing that...you really aren't making much sense at all.

    I'm really bored from some random guy think he is a priest of C# and quote the word "You should not use struct too big, change it to class". Please stop, I know, you never think outside their box

    First off, I nor anyone else here ever told you do to any such thing. I told you different ways to deal with a struct depending on whether or not it is large or small. If it's small, then copying it isn't a problem. Passing a reference to a small struct is MORE work than just copying the entire thing. If the struct is large then copying it is indeed a potential problem and there is at least a valid argument for attempting to avoid a copy. I named several potential options; none of them involved changing the struct to a class.

    Just add some feature like this than C# speed can boost to equal C++ but people like you try to be a hindrance to us who need performance in a C# world. That's sucks

    You're not going to see C# have the low level control of C++. Ever. It's simply not going to happen due to the purpose and design of the language.

    That said, adding this feature in no way adds and potential speed boost to the language. As I have already told you, you can use a ref/out parameter with a struct. This would merely be an attempt to accomplish the same goal with in a syntactically easier way. It's implementation may in fact end up being identical (that's how I would try to implement this feature anyway).

    Friday, February 24, 2012 4:11 PM
  • Because you don't understand the use case of my feature

    You just confuse how to use this feature and just think you know everything so you try to tell me another nonsense out of my point

    I don't know if you understand the implications of your own use case.  If the syntax you provided in the OP were allowed then you would be returning a pointer to a location in memory that potentially may not exist at a later point in time.  It's not a local variable, it's an instance one, so it's less likely to break, but that much harder to diagnose when does (or if it will).
    Friday, February 24, 2012 4:21 PM
  • If you know what I try to do then you should know this is to avoid that "property decrease performance" problem. By allow returning of reference to struct it then make str. And property will be used for safe access of class and little ValueType like int and float

    Really, man, struct won't do thing with GC. What make performance drop from struct is because we lack this feature I talk about. You always need to copy it especially from get/set is double copy that's why we always avoid making big struct in C#. But the reason is performance will drop from copying and that's all

    And you not try to understand this point and everything I told that's why you still think inside the box and still go against me with nonsense reason. Returning the reference of struct is another story from all those above. It make struct can move around in class manner but still alive without GC

    YES! YOU HAVE NO IDEA! SO YOU SHOULD TRY TO GET THE IDEA FIRST BEFORE GO AGAINST OTHER! GOD DAMN!

    I ALREADY KNOW THING TO MAKE IT WORK! BUT NOW I JUST REQUEST FEATURE. LISTEN! I REQUEST FEATURE! TO MAKE IT WORK IN THE WAY IT SHOULD BE! NOT JUST DO IT WITH SOMETHING I ALWAYS DID

    C# can be replacement of C++ that's what it's possibility. You are not the one who decide what C# will not be able to. I can said too, You will see it even you will like it or not. And what you will do? Stop using it? Go ahead

    That's what requesting feature stand for

    Friday, February 24, 2012 4:41 PM
  • OPCode allow to do this feature. And Microsoft already try to implement it. It just need more time to checking and Microsoft just try to put effort on other issue people try to request

    And the breaking problem then is a problem that would error at runtime, not a problem to do

    If you do dirty work you should safe yourself by your own. If you just want to playsafe then don't use it

    Not so difference with unsafe code, or even array is breakable, you can put any number in bracket and BOOM! error! that's all


    • Marked as answer by Thaina Friday, February 24, 2012 4:45 PM
    • Unmarked as answer by Thaina Friday, February 24, 2012 4:46 PM
    • Edited by Thaina Friday, February 24, 2012 4:46 PM
    Friday, February 24, 2012 4:45 PM