文章目录
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学习笔记目录整理