由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则用在需要被调用的方法修改调用者的引用的时候,可以不断改变引用地址对应的值。

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

你可能感兴趣的:(parse)