/// <summary> /// 从当前数组的指定索引开始截取指定长度的一部分。 /// 如果 <paramref name="startIndex"/> 小于 <c>0</c>, /// 那么表示从字符串结束位置向前计算的位置。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要截取的数组。</param> /// <param name="startIndex">要截取的起始索引。</param> /// <param name="length">要截取的数组元素个数。</param> /// <returns>截取得到的数组。</returns> /// <exception cref="System.ArgumentNullException"> /// <paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="startIndex"/> 小于负的此数组的长度。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="length"/> 小于 <c>0</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="startIndex"/> 加 <paramref name="length"/> /// 之和指示的位置不在此数组中。</exception> public static T[] Subarray <T>(this T[] array, int startIndex, int length) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (startIndex < -array.Length) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } if (length < 0 || startIndex + length > array.Length) { throw CommonExceptions.InvalidOffsetLength(); } Contract.Ensures(Contract.Result <T[]>() != null); if (length == 0) { return(Empty <T>()); } if (startIndex < 0) { startIndex += array.Length; } return(SubarrayInternal(array, startIndex, startIndex + length)); }
/// <summary> /// 从当前数组的指定索引开始截取到指定索引结束的一部分。 /// 如果 <paramref name="startIndex"/> 或 <paramref name="endIndex"/> /// 小于 <c>0</c>,那么表示从数组末尾向前计算的位置。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要截取的数组。</param> /// <param name="startIndex">要截取的起始索引。</param> /// <param name="endIndex">要截取的结束索引,但不包括该位置的元素。</param> /// <returns>截取得到的数组。如果 <paramref name="startIndex"/> 等于数组的长度或大于等于 /// <paramref name="endIndex"/> ,则为空数组。</returns> /// <exception cref="System.ArgumentNullException"> /// <paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="startIndex"/> 或 <paramref name="endIndex"/> /// 指示的位置不在此数组中。</exception> public static T[] Slice <T>(this T[] array, int startIndex, int endIndex) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (startIndex < -array.Length || startIndex > array.Length) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } if (endIndex < -array.Length || endIndex > array.Length) { throw CommonExceptions.ArgumentOutOfRange("endIndex", endIndex); } Contract.Ensures(Contract.Result <T[]>() != null); if (startIndex == endIndex) { return(Empty <T>()); } if (startIndex < 0) { startIndex += array.Length; } if (endIndex < 0) { endIndex += array.Length; } if (startIndex < endIndex) { return(SubarrayInternal(array, startIndex, endIndex)); } return(Empty <T>()); }
/// <summary> /// 基于参数类型,从给定的方法集中选择一个方法。 /// 允许通过指定 <see cref="BindingFlags.OptionalParamBinding"/> 来匹配可选参数。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="match">用于匹配的候选方法集。</param> /// <param name="types">用于定位匹配方法的参数类型。</param> /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param> /// <returns>如果找到,则为匹配的方法;否则为 <c>null</c>。</returns> public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers) { if (match == null) { throw CommonExceptions.ArgumentNull("match"); } if (match.Length == 0) { throw CommonExceptions.ArrayEmpty("match"); } // 构造方法信息数组。 MatchInfo[] infos = new MatchInfo[match.Length]; MatchInfo info = null; int idx = 0; for (int i = 0; i < match.Length; i++) { if (match[i] != null) { info = new MatchInfo(match[i]); int len = info.Parameters.Length > types.Length ? info.Parameters.Length : types.Length; info.ParamOrder = info.ParamOrderRev = MethodExt.GetParamOrder(len); infos[idx++] = info; } } info = SelectMethod(bindingAttr, infos, idx, types); if (info == null) { return(null); } return(info.Method); }
public static T[,] Random <T>(this T[,] array) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <T[, ]>() != null); int w = array.GetLength(1); int idx = array.Length; for (int i = array.GetLength(0) - 1; i >= 0; i--) { for (int j = w - 1; j >= 0; j--) { int r = RandomExt.Next(idx--); int x = r % w; int y = r / w; if (y != i || x != j) { T temp = array[i, j]; array[i, j] = array[y, x]; array[y, x] = temp; } } } return(array); }
/// <summary> /// 将数组使用指定的值填充。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要填充的数组。</param> /// <param name="value">要填充数组的值。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> public static T[] Fill <T>(this T[] array, T value) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <T[]>() != null); return(FillInternal(array, value, 0, array.Length)); }
/// <summary> /// 将数组使用指定的值填充。 /// </summary> /// <param name="array">要填充的数组。</param> /// <param name="value">要填充数组的值。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> /// <overloads> /// <summary> /// 将数组使用指定的值填充。 /// </summary> /// </overloads> public static Array Fill(this Array array, object value) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <Array>() != null); return(FillInternal(array, value, 0, array.Length)); }
/// <summary> /// 将数组从指定的索引位置开始使用指定的值填充。 /// </summary> /// <param name="array">要填充的数组。</param> /// <param name="value">要填充数组的值。</param> /// <param name="startIndex">要开始填充的起始索引。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="startIndex"/> /// 小于零或大于等于数组的长度。</exception> public static Array Fill(this Array array, object value, int startIndex) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (startIndex < 0 || startIndex >= array.Length) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } Contract.Ensures(Contract.Result <Array>() != null); return(FillInternal(array, value, startIndex, array.Length - startIndex)); }
/// <summary> /// 将数组使用指定的值填充。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要填充的数组。</param> /// <param name="value">要填充数组的值。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> public static T[][] Fill <T>(this T[][] array, T value) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <T[][]>() != null); for (int i = array.Length - 1; i >= 0; i--) { for (int j = array[i].Length - 1; j >= 0; j--) { array[i][j] = value; } } return(array); }
/// <summary> /// 初始化方法字典。 /// </summary> /// <param name="methods">方法列表。</param> private void InitMethods(Delegate[] methods) { methodDict = new Dictionary <Type, TDelegate>(methods.Length); for (int i = 0; i < methods.Length; i++) { if (methods[i] == null) { throw CommonExceptions.ArgumentNull("methods[" + i + "]"); } TDelegate dlg = methods[i].Wrap <TDelegate>(); if (dlg == null) { throw CommonExceptions.DelegateCompatible("methods[" + i + "]", typeof(TDelegate)); } methodDict.Add(methods[i].GetType().GetMethod("Invoke").GetParameters()[keyIndex].ParameterType, dlg); } }
/// <summary> /// 返回指定字符串中位于指定位置的字符的宽度。 /// </summary> /// <param name="str">要获取宽度的字符字符串。</param> /// <param name="index"><paramref name="str"/> 中的字符位置。</param> /// <returns><paramref name="str"/> 中指定字符的宽度,结果可能是 <c>0</c>、<c>1</c> 或 <c>2</c>。</returns> /// <remarks>此方法基于 Unicode 标准 6.3 版。详情请参见 /// <see href="http://www.unicode.org/reports/tr11/">Unicode Standard Annex #11 EAST ASIAN WIDTH</see>。 /// 返回 <c>0</c> 表示控制字符、非间距字符或格式字符,<c>1</c> 表示半角字符, /// <c>2</c> 表示全角字符。</remarks> /// <exception cref="ArgumentNullException"><paramref name="str"/> 为 <c>null</c>。</exception> /// <exception cref="IndexOutOfRangeException"><paramref name="index"/> 大于等于字符串的长度或小于零。</exception> /// <seealso href="http://www.unicode.org/reports/tr11/">Unicode Standard Annex #11 EAST ASIAN WIDTH</seealso>。 public static int Width(string str, int index) { if (str == null) { throw CommonExceptions.ArgumentNull("str"); } if (index < 0) { throw CommonExceptions.ArgumentNegative("index", index); } if (index >= str.Length) { throw CommonExceptions.ArgumentOutOfRange("index", index); } Contract.Ensures(Contract.Result <int>() >= 0 && Contract.Result <int>() <= 2); return(Width(char.ConvertToUtf32(str, index))); }
/// <summary> /// 从当前数组的指定索引开始截取一部分。 /// 如果 <paramref name="startIndex"/> 小于 <c>0</c>, /// 那么表示从字符串结束位置向前计算的位置。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="startIndex">要截取的起始索引。</param> /// <param name="array">要截取的数组。</param> /// <returns>截取得到的数组。</returns> /// <exception cref="System.ArgumentNullException"> /// <paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="startIndex"/> 小于负的数组的长度。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="startIndex"/> 大于数组的长度。</exception> /// <overloads> /// <summary> /// 从当前数组的指定索引开始截取一部分。 /// </summary> /// </overloads> public static T[] Subarray <T>(this T[] array, int startIndex) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (startIndex < -array.Length || startIndex > array.Length) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } Contract.Ensures(Contract.Result <T[]>() != null); if (startIndex == array.Length) { return(Empty <T>()); } return(Subarray(array, startIndex, array.Length - startIndex)); }
/// <summary> /// 将数组从指定的索引位置开始使用指定的函数的返回值填充。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要填充的数组。</param> /// <param name="value">返回要填充数组的值的函数,其参数是当前填充到的索引。</param> /// <param name="startIndex">要开始填充的起始索引。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="startIndex"/> /// 小于零或大于等于数组的长度。</exception> public static T[] Fill <T>(this T[] array, Func <int, T> value, int startIndex) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (value == null) { throw CommonExceptions.ArgumentNull("value"); } if (startIndex < 0 || startIndex >= array.Length) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } Contract.Ensures(Contract.Result <T[]>() != null); return(FillInternal(array, value, startIndex, array.Length - startIndex)); }
/// <summary> /// 将数组进行随机排序。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要进行随机排序的数组。</param> /// <returns>已完成随机排序的数组。</returns> /// <remarks>应保证每个元素出现在每个位置的概率基本相同。 /// 采用下面的代码进行测试: /// <code>int size = 10; /// int[] arr = new int[size]; /// int[,] cnt = new int[size, size]; /// for (int i = 0; i { 200; i++) /// { /// arr.Fill(n => n).Random(); /// for (int j = 0; j { size; j++) cnt[j, arr[j]]++; /// } /// for (int i = 0; i { size; i++) /// { /// for (int j = 0; j { size; j++) /// Console.Write("{0} ", cnt[i, j]); /// Console.WriteLine(); /// }</code> /// </remarks> /// <overloads> /// <summary> /// 将数组进行随机排序。 /// </summary> /// </overloads> public static T[] Random <T>(this T[] array) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <T[]>() != null); for (int i = array.Length - 1; i > 0; i--) { int j = RandomExt.Next(i + 1); if (j != i) { T temp = array[i]; array[i] = array[j]; array[j] = temp; } } return(array); }
public static T[, ,] Fill <T>(this T[, ,] array, T value) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } Contract.Ensures(Contract.Result <T[, , ]>() != null); for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { for (int k = 0; k < array.GetLength(2); k++) { array[i, j, k] = value; } } } return(array); }
/// <summary> /// 将数组使用指定的函数的返回值填充。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">要填充的数组。</param> /// <param name="value">返回要填充数组指定索引的值的函数,其参数是当前填充到的索引。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentNullException"><paramref name="value"/> 为 <c>null</c>。</exception> public static T[][] Fill <T>(this T[][] array, Func <int, int, T> value) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (value == null) { throw CommonExceptions.ArgumentNull("value"); } Contract.Ensures(Contract.Result <T[][]>() != null); for (int i = 0; i < array.Length; i++) { for (int j = 0; j < array[i].Length; j++) { array[i][j] = value(i, j); } } return(array); }
/// <summary> /// 将数组从指定的索引位置开始使用指定的函数的返回值填充指定的长度。 /// </summary> /// <param name="array">要填充的数组。</param> /// <param name="value">返回要填充数组指定索引的值的函数,其参数是当前填充到的索引。</param> /// <param name="startIndex">要开始填充的起始索引。</param> /// <param name="length">要填充的数组元素个数。</param> /// <returns>填充完毕的数组。</returns> /// <exception cref="System.ArgumentNullException"><paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentNullException"><paramref name="value"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="startIndex"/> /// 加 <paramref name="length"/> 之和大于数组的长度。</exception> /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="startIndex"/> /// 或 <paramref name="length"/> 小于零。</exception> public static Array Fill(this Array array, Func <int, object> value, int startIndex, int length) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (value == null) { throw CommonExceptions.ArgumentNull("value"); } if (startIndex < 0) { throw CommonExceptions.ArgumentOutOfRange("startIndex", startIndex); } if (length < 0 || startIndex + length > array.Length) { throw CommonExceptions.ArgumentOutOfRange("length", length); } Contract.Ensures(Contract.Result <Array>() != null); return(FillInternal(array, value, startIndex, length)); }
/// <summary> /// 从当前数组的右端截取一部分。 /// </summary> /// <typeparam name="T">数组中元素的类型。</typeparam> /// <param name="array">从该数组返回其最右端截取的部分。</param> /// <param name="length">要截取的元素个数。 /// 如果为 <c>0</c>,则返回空数组。如果大于或等于 <paramref name="array"/> 的长度, /// 则返回整个数组的一个浅拷贝。</param> /// <returns>从指定数组的右端截取的部分。</returns> /// <exception cref="System.ArgumentNullException"> /// <paramref name="array"/> 为 <c>null</c>。</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// <paramref name="length"/> 小于 <c>0</c>。</exception> public static T[] Right <T>(this T[] array, int length) { if (array == null) { throw CommonExceptions.ArgumentNull("array"); } if (length < 0) { throw CommonExceptions.ArgumentOutOfRange("length", length); } Contract.Ensures(Contract.Result <T[]>() != null); if (length == 0) { return(Empty <T>()); } if (length > array.Length) { length = array.Length; } return(SubarrayInternal(array, array.Length - length, length)); }
/// <summary> /// 基于提供的参数,从给定的方法集中选择要调用的方法。 /// </summary> /// <param name="bindingAttr"><see cref="System.Reflection.BindingFlags"/> 值的按位组合。</param> /// <param name="match">用于匹配的候选方法集。</param> /// <param name="args">传入的参数。</param> /// <param name="modifiers">使绑定能够处理在其中修改了类型的参数签名的参数修饰符数组。</param> /// <param name="culture">一个 <see cref="System.Globalization.CultureInfo"/> 实例, /// 用于在强制类型的联编程序实现中控制数据类型强制。</param> /// <param name="names">参数名(如果匹配时要考虑参数名)或 <c>null</c>(如果要将变量视为纯位置)。</param> /// <param name="state">方法返回之后,<paramref name="state"/> 包含一个联编程序提供的对象, /// 用于跟踪参数的重新排序。</param> /// <returns>匹配的方法。</returns> public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) { if (match == null) { throw CommonExceptions.ArgumentNull("match"); } if (match.Length == 0) { throw CommonExceptions.ArrayEmpty("match"); } // 检查参数名称数组,不能出现名称相同的两个参数。 if (names != null) { CheckNames(names); } // 构造方法信息数组。 MatchInfo[] infos = new MatchInfo[match.Length]; MatchInfo info = null; int idx = 0; for (int i = 0; i < match.Length; i++) { if (match[i] != null) { info = new MatchInfo(match[i]); int len = info.Parameters.Length > args.Length ? info.Parameters.Length : args.Length; if (names == null) { info.ParamOrder = info.ParamOrderRev = MethodExt.GetParamOrder(len); } else { info.ParamOrder = new int[len]; // 根据 names 创建参数顺序。 if (!CreateParamOrder(info.ParamOrder, info.Parameters, names)) { continue; } } infos[idx++] = info; } } if (idx == 0) { // 没有可匹配的方法。 state = null; return(null); } Type[] types = new Type[args.Length]; for (int i = 0; i < args.Length; i++) { // types[i] 为 null 表示可以匹配任何引用类型。 if (args[i] != null) { types[i] = args[i].GetType(); } } info = SelectMethod(bindingAttr, infos, idx, types); if (info == null) { // 没有可匹配的方法。 state = null; return(null); } UpdateArgs(info, ref args, names != null, out state); return(info.Method); }