• 由TryParse到out/ref


    先看一下这段代码,使用reflector反编译过来的

    public static bool TryParse(string s, out int result)
    {
        return Number.TryParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
    }
    
     

    可知TryParse()返回的是一个bool类型,这里还使用了个out关键字。

    首先解决TryParse()这个问题

    (1)TryParse()在进行转换时,先进行尝试转换,如果转换失败,返回0

       static void Main(string[] args)
            {
                string a = "234dff";
                int b;
                int.TryParse(a, out b);
                Console.WriteLine(b);
                Console.ReadLine();
            }

    如果转换成功,返回int类型的值

    int.TryParse(a, out b); 是指将字符串强制转换并且赋值给b,这里必须使用out关键字修饰,至于为什么使用待会再说。
    (2)将一个字符串转换成一个相应类型的值时,可以使用Convert() Parse(),那么这三者有什么区别?
            static void Main(string[] args)
            {
                string a = "234dff";
                int b;
                int.TryParse(a, out b);//不报错,返回一个结果为0
                // b = Convert.ToInt32(a);//报错类型输入的字符串不正确
                // b = int.Parse(a);//报错类型输入的字符串不正确
                Console.WriteLine(b);
                Console.ReadLine();
            }

    int.Parse()

    public static int Parse(string s)
    {
        return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
    }

    Convert.ToInt32()  不安全的类型

    [SecuritySafeCritical]
    public static unsafe int ToInt32(byte[] value, int startIndex)
    {
        if (value == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
        }
        if (((ulong) startIndex) >= value.Length)
        {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
        }
        if (startIndex > (value.Length - 4))
        {
            ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
        }
        fixed (byte* numRef = &(value[startIndex]))
        {
            if ((startIndex % 4) == 0)
            {
                return *(((int*) numRef));
            }
            if (IsLittleEndian)
            {
                return (((numRef[0] | (numRef[1] << 8)) | (numRef[2] << 0x10)) | (numRef[3] << 0x18));
            }
            return ((((numRef[0] << 0x18) | (numRef[1] << 0x10)) | (numRef[2] << 8)) | numRef[3]);
        }
    }
    
     
    
     

    如果我们将这三者的转换能力排个序,那么TryParse()>Parse()>Convert()

    再说说TryParse(string s, out int b)中的关键字out(说白了就是表明我这个参数是用来传出的)

      (1)在方法的参数类型前加out,那么传参数的时候也必须在参数前加out表明这个参数不是传入的,而是用来传出值的。

    (2)如果参数是out形式传入的,那么在传入前可以不赋初值。

    (3)在方法中对于out修饰的参数,必须在使用前先赋值。

    class Program
        {
            static void Main(string[] args)
            {
                int number=2;
                Test(out number);
                Console.WriteLine(number);
                Console.ReadLine();
            }
            static void Test(out int b)
            {
                int c = 100;
                b =c+1;
            }
        }
    结果是101

    具体用法变化很多

    说到这,还有个ref关键字(这个关键字

    ref:引用传递,传递的是地址。既能传值,又能赋值(地址)。

    class Program
        {
            static void Main(string[] args)
            {
                int number=2;
                Test(ref number);
                Console.WriteLine(number);
                Console.ReadLine();
            }
            static void Test(ref int b)
            {
                int c = 100;
                b =c+1;
            }
        }

    结果:`101

    好像没有什么区别是的。

    接着改改看

    class Program
        {
            static void Main(string[] args)
            {
                int b = 10;
                Test(ref b);
                Console.ReadLine();
            }
            static void Test(ref int b)
            {
                Console.WriteLine(b);
            }
        }

    结果是10

     class Program
        {
            static void Main(string[] args)
            {
                int b = 10;
                Test(out b);
                Console.ReadLine();
            }
            static void Test(out int b)
            {
                Console.WriteLine(b);
            }
        }

    错误 1 使用了未赋值的 out 参数“b” 

    编译未通过

    到这也就说明了问题的本质了:

    (1)使用out必须在方法返回之前或再使用out参数前为 out 参数赋值,也就是说out不能接受地址没有值的参数;而ref可以。

    (2)out参数传递进来的是值的拷贝,传递出去的是什么就看代码怎么写了;ref传递进来的是值的引用地址,这个地址可以是空的引用。

    总之:out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候,可以不断改变引用地址对应的值。

    我小小菜鸟一个,不到之处,敬请拍砖!

  • 相关阅读:
    记一次ntp反射放大ddos攻击
    除了binlog2sql工具外,使用python脚本闪回数据(数据库误操作)
    vmware linux虚拟机忘记密码怎么办
    flask(二)
    flask(一)
    发布一个Django项目
    nginx的使用
    redis的下载及使用
    Linux虚拟机没有IP的解决办法
    Mariadb的安装与使用
  • 原文地址:https://www.cnblogs.com/chenyongblog/p/2963841.html
Copyright © 2020-2023  润新知