【Unity】Unity开发进阶(五)ArrayHelper数组帮助类


ArrayHelper

程序开发的过程中经常会遇到数组,数组的查找、排序也是经常要用到的功能。市面上已经有很多成熟的工具了,最出名的莫过于LINQ了,但是LINQ有时候用起来过于庞大了,所以我们自己做一个简单的数组帮助类来完成相应的功能。

先说说什么是LINQ吧。

LINQ

语言集成查询(英语:Language Integrated Query,缩写:LINQ),发音"link",是微软的一项技术,新增一种自然查询的SQL语法到.NET Framework的编程语言中,当前可支持C#以及Visual Basic .NET语言。2007年11月19日随.NET Framework 3.5发布了LINQ技术。

从技术角度而言,LINQ定义了大约40个查询操作符,如select、from、in、where以及order by(C#中)。使用这些操作符可以编写查询语句。不过,这些查询还可以基于很多类型的数据,每个数据类型都需要一个单独的LINQ类型。

数组帮助类

由于IOS平台不支持LINQ语言集成查询(IOS禁止动态创建对象,会出现JIT错误),如果项目要考虑在IOS平台发布的话,可以自己开发一个数组帮助类(ArrayHelper),其中提供数组的常用操作,例如:查找元素、排序、最大值、最小值等。

具体代码如下:

using System;
using System.Collections.Generic;

namespace Common
{
    
    
    /// <summary>
    /// 选择委托:负责 从某个类型中 选取某个字段 返回这个字段的值
    /// 例如:               学生类中          年龄                           值 20!
    /// </summary>
    /// <typeparam name="T">数据类型: Student</typeparam>
    /// <typeparam name="TKey">数据类型的字段的类型 :Age int</typeparam>
    /// <param name="t">数据类型的对象: zsObj</param>
    /// <returns>对象的某个字段的值:zsObj.Age  20</returns>

    public delegate TKey SelectHandler<T, TKey>(T t);

    /// <summary>
    /// 查找条件委托:表示一个查找条件,例如:
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t"></param>
    /// <returns></returns>
    public delegate bool FindHandler<T>(T t);

    /// <summary>
    /// 数组帮助类
    /// 该类为数组提供了查找排序等方法,并通过扩展参数将这些工具方法扩展到原有数组中,方便直接调用
    /// 使用方法:
    /// 1、 引入当前包:using Common;
    /// 2、 使用数组调用方法:myArray.Find(s => s.studentName == name); // 根据名字查找学生
    /// </summary>
    public static class ArrayHelper
    {
    
    

        /// <summary>
        /// 数组查找功能(单个结果)
        /// 通过委托方法中提供的条件找到相应的元素
        /// 例:myArray.Find(s => s.studentName == name); // 根据名字查找学生
        /// </summary>
        /// <typeparam name="T">数组元素泛型</typeparam>
        /// <param name="array">数组本身(注意:此方法会被扩展到数组本身)</param>
        /// <param name="handler">委托方法,用于提供查询条件</param>
        /// <returns>第一个满足条件的数组元素</returns>
        public static T Find<T>(this T[] array, FindHandler<T> handler)
        {
    
    
            T temp = default(T);
            for (int i = 0; i < array.Length; i++)
            {
    
    
                if (handler(array[i]))
                {
    
    
                    return array[i];
                }
            }
            return temp;
        }

        /// <summary>
        /// 数组查找功能(多个结果)
        /// 通过委托方法中提供的条件找到相应的元素
        /// 例:myArray.FindAll(s => s.age > 12); // 根据年龄查找学生
        /// </summary>
        /// <typeparam name="T">数组元素泛型</typeparam>
        /// <param name="array">数组本身(注意:此方法会被扩展到数组本身)</param>
        /// <param name="handler">委托方法,用于提供查询条件</param>
        /// <returns>所有满足条件的数组元素</returns>
        public static T[] FindAll<T>(this T[] array, FindHandler<T> handler)
        {
    
    
            List<T> list = new List<T>();
            for (int i = 0; i < array.Length; i++)
            {
    
    
                if (handler(array[i]))
                {
    
    
                    list.Add(array[i]);
                }
            }
            return list.ToArray();
        }

        //选择:选取数组中对象的某些成员形成一个独立的数组
        //多个学生【id age tall score】   【60,50,70,80】
        //                                              【“zs”,“ls”】
        /// <summary>
        /// 将数组对象中的某个字段做成数组返回
        /// 例:myArray.Select(s => s.studentName); // 查找所有学生的姓名
        /// 返回数组:["小明", "小花", "小蓝", "小粉"]
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="array"></param>
        /// <param name="handler"></param>
        /// <returns></returns>
        public static TKey[] Select<T, TKey>(this T[] array, SelectHandler<T, TKey> handler)
        {
    
    
            TKey[] keys = new TKey[array.Length];
            for (int i = 0; i < array.Length; i++)
            {
    
    
                keys[i] = handler(array[i]);
            }
            return keys;
        }

        /// <summary>
        /// 升序排序
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <typeparam name="TKey">数据类型字段的类型</typeparam>
        /// <param name="array">数据类型对象的数组</param>
        /// <param name="handler">
        /// 委托对象:负责 从某个类型中选取某个字段 返回这个字段的值
        /// </param>
        public static void OrderBy<T, TKey>(this T[] array, SelectHandler<T, TKey> handler) where TKey : IComparable<TKey>//对象 非 默认字段 数组比较
        {
    
    
            for (int i = 0; i < array.Length; i++)
            {
    
    
                for (int j = i + 1; j < array.Length; j++)
                {
    
    
                    //默认    张三 年龄  李四 年龄  if (array[i].CompareTo(array[j]) > 0)
                    //非默认 张三 身高  李四 身高  if (compare.Compare(array[i],array[j])>0)     
                    //使用委托取属性的值 去比较
                    if (handler(array[i]).CompareTo(handler(array[j])) > 0)
                    {
    
    
                        var temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }

        /// <summary>
        /// 降序排序
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <typeparam name="TKey">数据类型字段的类型</typeparam>
        /// <param name="array">数据类型对象的数组</param>
        /// <param name="handler">
        /// 委托对象:负责 从某个类型中选取某个字段 返回这个字段的值
        /// </param>
        public static void OrderByDescending<T, TKey>(this T[] array, SelectHandler<T, TKey> handler) where TKey : IComparable<TKey>
        {
    
    
            for (int i = 0; i < array.Length; i++)
            {
    
    
                for (int j = i + 1; j < array.Length; j++)
                {
    
    
                    if (handler(array[i]).CompareTo(handler(array[j])) < 0)
                    {
    
    
                        var temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }


        /// <summary>
        /// 返回最大的
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <typeparam name="TKey">数据类型字段的类型</typeparam>
        /// <param name="array">数据类型对象的数组</param>
        /// <param name="handler">
        /// 委托对象:负责 从某个类型中选取某个字段 返回这个字段的值
        /// </param>
        public static T Max<T, TKey>(this T[] array, SelectHandler<T, TKey> handler) where TKey : IComparable<TKey>
        {
    
    
            T temp = default(T);
            temp = array[0];
            for (int i = 1; i < array.Length; i++)
            {
    
    
                if (handler(temp).CompareTo(handler(array[i])) < 0)
                {
    
    
                    temp = array[i];
                }
            }
            return temp;
        }

        /// <summary>
        /// 返回最小的
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <typeparam name="TKey">数据类型字段的类型</typeparam>
        /// <param name="array">数据类型对象的数组</param>
        /// <param name="handler">
        /// 委托对象:负责 从某个类型中选取某个字段 返回这个字段的值
        /// </param>
        public static T Min<T, TKey>(this T[] array, SelectHandler<T, TKey> handler) where TKey : IComparable<TKey>
        {
    
    
            T temp = default(T);
            temp = array[0];
            for (int i = 1; i < array.Length; i++)
            {
    
    
                if (handler(temp).CompareTo(handler(array[i])) > 0)
                {
    
    
                    temp = array[i];
                }
            }
            return temp;
        }
    }

}

注意:上述代码会将这些方法都扩展到数组类中,使用时可以通过数组对象直接调用,无需使用帮助类类名,具体代码如下:

using Common;

public class TestArrayHelp
{
    
    
	// 学生数组(未初始化)
	public Student[] students;
	
    /// <summary>
    /// 根据名字查找学生
    /// </summary>
    /// <param name="name">学生姓名</param>
	private void getStudent(String name)
    {
    
    
    	// 根据名字查找学生
        Student stu = students.Find(s => s.studentName == name);
    }
}

关于扩展方法的详细内容请查看【Unity】Unity开发进阶(七)双刃剑:扩展方法

LINQ插件

如果一定要支持IOS,可以考虑一个叫IOS for LINQ(或LINQ to IOS)的插件。

总结

如果LINQ展开来讲其实也会有很多内容,类似于Hibernate,我自己之前做Java开发时也开发过类似的功能。

其实此类功能开发并不复杂,从功能上来讲大部分就是查询和排序之类的,其实现原理也大多数是利用反射+表达式(LINQ中又利用到了委托),从性能方面考虑的话,反射和委托其实都不适合反复使用(因为经常会造成内存泄漏),所以我个人觉得非必要情况下尽量不使用LINQ,基本的功能自己实现就好了,而且自己实现的代码便于掌控,更便于自己掌控项目性能。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

猜你喜欢

转载自blog.csdn.net/xiaoyaoACi/article/details/125016651
今日推荐