从小的地方开始优化自己的代码C# UNITY开发

目录

c#中关于list<>的查找

关于快速比较两个list所包含相同元素

关于list的排序

关于字符判断是否为空的比较

关于unity中判断GameObject是否为空使用obj==null性能消耗的问题

关于StringBuilder的使用


自己查阅资料整理的一些小的优化点,记录一下,有错误的地方有大佬发现也请指出,不甚感激。

c#中关于list<>的查找

仅查询是否包含此元素,Contains()效率最高,但只会返回bool值,使用哈希表或其他数据结构来进行快速查找,不会随着列表大小的增加而变慢,其时间复杂度通常为 O(1);


IndexOf()可以返回当前相同元素的index,会遍历整个列表来查找元素,重复元素时可能遍历多次,只返回首个相同元素index,匹配不到返回-1,会随着列表大小的增加而变慢,时间复杂度为 O(n);


FirstOrDefault()和IndexOf()类似,在查询时可以应对更复杂的比较情况,不会返回索引值,返回当前匹配到的元素,匹配不到返回0;


Find()和FirstOrDefault()使用类似,匹配不到返回空;

使用for循环虽然也是遍历,但是只遍历一次,也可以在匹配到相同元素后跳出,所以相对会节省一些性能;

关于快速比较两个list<Class>所包含相同元素
public class Class
{
    public string name;
    public int id;

    //重写比较 //但是这里有装箱拆箱的操作
    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
            return false;
    
        TestClass other = (TestClass)obj;
        return id == other.id && name == other.name;
    }
    
    public override int GetHashCode()
    {
        return HashCode.Combine(id, name);
    }
}
//看实际使用决定用哪种方式重写
//实现 IEqualityComparer<Class> 接口并重写 Equals 和 GetHashCode 方法可避免装箱拆箱
class ClassEqualityComparer : IEqualityComparer<TestClass>
{
    public bool Equals(TestClass x, TestClass y)
    {
        return x.id == y.id && x.name == y.name;
    }

    public int GetHashCode(TestClass obj)
    {
        return HashCode.Combine(obj.id, obj.name);
    }
}


//使用示例
 IEnumerable<Class> commonElements = list1.Intersect(list2); 
//或者
 IEnumerable<Class> commonElements = list1.Intersect(list2,new ClassEqualityComparer());

Intersect()相比嵌套for循环更简洁更高效

关于list<T>的排序

1.list<T>中的Sort(); // 默认按升序排序

2.LINQ中的OrderBy()// 默认按升序排序 和OrderByDescending()// 按降序排序

public class Class
{
    public int id;
}

List<Class> list;//假如里面有数据

list.Sort((x, y) => x.id.CompareTo(y.id)); //Sort原地排序不会产生新的list更节省性能

List<Class> list_1 = list.OrderByDescending(x => x.id).ToList();//需要list接收,OrderBy用法一样

总结一下排序这里,Sort 在原有的list中排序,OrderBy会产生一个新list,不考虑使用场景只是排序,Sort会更高效。需要保留原有list就用OrderBy或OrderByDescending。

关于字符判断是否为空的比较

开发中经常遇到需要判断字符串是否为空的判断,经常出现的有几种方式:

//空字符串是指字符串长度为0 字符串为空代表的是字符串是null(有点绕。。。)
str == null;//判断字符串是否为null 字符串长度为0的时候"" 可以通过判断

str ==""; //判断字符串是否为空字符串,会临时创建一个空字符串,不建议使用

str.length==0; //根据字符串长度判断字符串是否为空字符串,最节省性能,只有一个整数比较

string.IsNullOrEmpty();//用于同时检查字符串是否为 null 或者为空字符串,相当于1,3结合比较

str.Equals(null) //不能这么用,始终都会返回false 而且如果字符串为空会抛异常

最常用的还是最后一种,这里只是解释一下这几种方式的区别 。(因为很久之前面试的时候遇到过这样的问题。)

关于unity中判断GameObject是否为空使用obj==null性能消耗的问题

先说我自己的结论,'=='运算有额外消耗,但是不大,而且'=='运算最为准确 ,可以使用.

经过种种查询得知,unity中重载了==运算符,来检测游戏对象obj是否为空,每次使用==unity不仅会检查内存地址,还会额外查询销毁状态,所以会多消耗一些性能,据说问题不大.

我查到有推荐使用ReferenceEquals(obj,null);节省性能,来判断obj是否为空的方式,

但我在实际测试的发现了一些问题:

图中代码只有obj1进行了拖拽赋值,其余都是空的,但是ReferenceEquals()却出现了问题,本来应该为空的obj2,obj4被判断为有值,只有私有的obj3得到了正确得判断.

这里就涉及到unity的特殊的处理了,public 会显示到面板上的游戏对象会被序列化,所以在私有的对象上面加上序列化就会造成一样的效果,unity给了他们一个不是空的空值...这个值unity自己是知道他是空的,所以通过unity重载的'=='运算符可以判断出正常的结果,ReferenceEquals()就不行了.

关于StringBuilder的使用

说到节省消耗StringBuilder总是少不了提到,但是这个什么用比较合适却一直没人说起,我们这里来简单的验证一下;

首先我们先了解一些StringBuilder()节省消耗的机制,它会在内部维护一个字符串数组,字符串频繁变更时相当于直接修改数组,普通'字符串'+'字符串'的操作会创建出新的对象,所以就会比较消耗性能.

但是这种字符串的+字符串的操作很快捷,简单易读,大家也很习惯了,所以我们就要实际的验证下,具体什么时候使用那种方式更合适.

这里我写了一个10000次for循环和很长的字符串,测试两种字符串拼接的时间,可以看出这种频繁的字符串操作StringBuilder()处理的时间可以说是遥遥领先;

这次循环100次,还缩短了字符串的长度,长度为10的字符串,时间差距就很小了 .

总结一下,处理很长,而且处理次数很多,而且频繁改动的数据(个人觉得最起码也要上百次的那种改动)就用StringBuilder();

不会频繁改动的,处理次数并不多的,直接+就好了.

整理补充中。。。

  • 26
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值