When is using the C# ref keyword ever a good idea?

后端 未结 10 799
情歌与酒
情歌与酒 2020-11-29 06:05

The more I see ref used in production code, the more misuse I encounter and the more pain it causes me. I have come to hate this keyword, because from a framework-building s

相关标签:
10条回答
  • 2020-11-29 06:18

    Hypothetically, I'd guess that you might use a lot of ref/out arguments if you intended to mimic the architecture of older procedural software, for example old game engines and so on. I've scanned the source code of one, I think it was Duke Nukem 3D, and it's procedural with lots of subroutines modifying variables in place, and almost no functions. Obviously, you'd be unlikely to program like this for a real production application unless you had some specific aim in mind.

    0 讨论(0)
  • 2020-11-29 06:19

    Any time you want to change the value of a value type - this happens a lot in cases where you want to efficiently update a pair of related values (i.e. rather than returning a struct containing two ints, you pass (ref int x, ref int y))

    0 讨论(0)
  • 2020-11-29 06:20

    It's useful when you need efficient in-place algorithms on bignums.

    0 讨论(0)
  • 2020-11-29 06:25

    I'm using ref quite often. Just think about functions with multiple return values. It doesn't make sense to create a return object (helper object) or even using hashtables for this purpose.

    Example:

     getTreeNodeValues(ref selectedValue, ref selectedText);
    

    Edit:

    It's better to use out here - as commented.

     getTreeNodeValues(out selectedValue, out selectedText);
    

    I'm using it for processing objects:

    MyCar car = new MyCar { Name="TestCar"; Wieght=1000; }
    
    UpdateWeight(ref car, 2000);
    
    0 讨论(0)
  • 2020-11-29 06:26

    Another useful example in addition to swap<> is this:

    Prompter.getString("Name ? ", ref firstName);
    Prompter.getString("Lastname ? ", ref lastName);
    Prompter.getString("Birthday ? ", ref firstName);
    Prompter.getInt("Id ? ", ref id);
    Prompter.getChar("Id type: <n = national id, p = passport, d = driver licence, m = medicare> \n? ", ref c);
    
    
    
    public static class Prompter
    {
        public static void getKey(string msg, ref string key)
        {
            Console.Write(msg);
            ConsoleKeyInfo cki = Console.ReadKey();
            string k = cki.Key.ToString();
            if (k.Length == 1)
                key = k;
        }
    
        public static void getChar(string msg, ref char key)
        {
            Console.Write(msg);
            key = Console.ReadKey().KeyChar;
            Console.WriteLine();
        }
    
        public static void getString(string msg, ref string s)
        {
            Console.Write(msg);
            string input = Console.ReadLine();
            if (input.Length != 0)
                s = input;
        }
    
        public static void getInt(string msg, ref int i)
        {
            int result;
            string s;
    
            Console.Write(msg);
            s = Console.ReadLine();
    
            int.TryParse(s, out result);
            if (result != 0)
                i = result;       
        }
    
        // not implemented yet
        public static string getDate(string msg)
        {
            // I should use DateTime.ParseExact(dateString, format, provider);
            throw new NotImplementedException();
        }    
    
    
    }
    

    Use out here it's not an option

    0 讨论(0)
  • 2020-11-29 06:28

    Maybe when you have a struct (which is a value type):

    struct Foo
    {
        int i;
    
        public void Test()
        {
            i++;
        }
    }
    
    static void update(ref Foo foo)
    {
        foo.Test();
    }
    

    and

    Foo b = new Foo();
    update(ref b);
    

    Here you would to use two-parameters with out like:

    static void update(Foo foo, out Foo outFoo) //Yes I know you could return one foo instead of a out but look below
    {
        foo.Test();
    
        outFoo = foo;
    }
    

    imaging the method having more than one Foo then you would get twice the parameters with out versus ref. An alternative is to return a N-tuple. I don't have a real-world example on when to use this stuff.

    Add on: Different .TryParse methods could also have avoided out if they returned Nullable<T> instead which essentially is a tuple of boolean * T.

    0 讨论(0)
提交回复
热议问题