C# 值类型调用ToString一定会装箱吗?

答案

可能会装箱。

解释

为什么是可能会装箱呢?
首先我们复习下装箱拆箱的概念

  • 装箱:值类型转换成引用类型
  • 拆箱:引用类型转换为值类型

那么如果要装箱,原来的类型一定要是值类型,目标类型一定要是引用类型

什么是值类型?ValueType是什么?

值类型其实就是ValueType
我们先来看ValueType里面有什么

namespace System
{
    public abstract class ValueType
    {
        protected ValueType();

        public override bool Equals(object obj);
        public override int GetHashCode();
        public override string ToString();
    }
}

首先,可以确定的是,ValueType是一个class,也就是一个类,但是它重写了Equals方法,那么ValueType对象在和其他对象做比较的时候,会和class有不同的处理方式,这也就是值类型引用类型不同的根源。

然后这里有个非常重要的地方,我们发现ValueType重写了ToString方法,我们先记住这里,再看看后面。

int是什么类型?

拿C#的int来做例子吧。
首先C#的int,它是System.Int32的简称,而System.Int32它是结构体,结构体都是默认继承ValueType,所以结构体是值类型。也就是说int就是值类型。

namespace System
{
    public struct Int32 : IComparable, IComparable<Int32>, IConvertible, IEquatable<Int32>, IFormattable
    {
        public const Int32 MaxValue = 2147483647;
        public const Int32 MinValue = -2147483648;

        public static Int32 Parse(string s, IFormatProvider provider);
        public static Int32 Parse(string s, NumberStyles style, IFormatProvider provider);
        public static Int32 Parse(string s, NumberStyles style);
        public static Int32 Parse(string s);
        public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out Int32 result);
        public static bool TryParse(string s, out Int32 result);
        public Int32 CompareTo(object value);
        public Int32 CompareTo(Int32 value);
        public bool Equals(Int32 obj);
        public override bool Equals(object obj);
        public override Int32 GetHashCode();
        public TypeCode GetTypeCode();
        public override string ToString();
        public string ToString(IFormatProvider provider);
        public string ToString(string format);
        public string ToString(string format, IFormatProvider provider);
    }
}

我们发现,int也是重写了ToString方法,也就是说,它会调用自己实现的ToString方法,而不是调用父类的ToString方法。

判断是否装箱的诀窍

看值类型有没有进行装箱,就看他有没有装换成Object或者值类型所继承的接口类型

实例

那么我们来看下方的代码

int age = 5;
string str = age.ToString();

我们先复习下

  1. 装箱:值类型转换成引用类型
  2. int是值类型
  3. int重写了ToString方法

请问:上面的代码装箱了吗?

先不揭晓答案。我们来看看ToString过程。

  1. age调用ToString方法,去int类型中寻找有没有ToString方法。
  2. 发现int重写了ToString方法,直接调用intToString方法。

答案:没有发生装箱。
原因:int自身有ToString的实现,所以就没有向父类查找了。也就不会发生装箱操作了。

拓展

我们可以自定义一个结构体,让他重新ToString方法,也不会发生装箱操作。

public struct A
{
    public int age;
    public string name;
    public A(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
    public override string ToString()
    {
        return name;
    }
}

如果我们不重写会怎么样呢?

public struct B
{
    public int age;
    public string name;
    public B(int age, string name)
    {
        this.age = age;
        this.name = name;
    }
}

答案是会装箱,因为ValueType本身是类,所以如果自身没有实现ToString方法,会从父类去寻找,然后找到了ValueType,但是ValueType是一个类,所以这个时候发生了多态,也就是从值类型转换成引用类型了,所以此时发生了装箱。

最后需要注意

我们在写代码的时候,字符串拼接比较常用,比如string和int拼接。

测试环境

Unity

第一种写法

private void Update()
{
    string s = "";
    int num = 1;
    s += num.ToString();
}

在这里插入图片描述

第二种写法

private void Update()
{
    string s = "";
    int num = 1;
    s += num;
}

在这里插入图片描述
所以我们需要多注意这个问题。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就一枚小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值