C#泛型与委托:一个简单的数组模板示例
2014-08-15 11:31
246 查看
以下是个人项目中可能会用到的一个二维数组模板,简便高效(?)
使用示例
生成的二维数组转换成灰度图像如下
瞬间科技感了~~~
还可以这样
添加噪声后的数组ic,现将其转换为byte数组
更加科技感了~~~
这个模板会用到个人的项目中,更多内容不便公开,待项目完成之后再公布。
如果不使用模板,那么针对每一种数据类型都要分别编写代码,
大量的重复工作,效率很低,因此建议使用泛型(Generics)和委托(Delegates).
LOG@ 2014/08/15 11:36 Fri. BJ
点此领取楼主 (本文全原创,转载请注明出处 http://blog.csdn.net/fengyhack)
using System; using System.Collections.Generic; namespace Array2DTemplate { public class Array2D<Ty> where Ty : struct // 泛型约束 Ty必须struct类型 { private int _row; private int _col; private Ty[,] _data; #region GetSet public Ty[,] Data { get { return _data; } set { _data = value; } } public int Row { get { return _row; } } public int Col { get { return _col; } } public void SetData(Ty[] buffer) { int _size = _row * _col; int size=buffer.Length; if(size<_size) { throw new Exception("Notenough size"); } int k = 0; for (int i = 0; i < _row; ++i) { for (int j = 0; j < _col; ++j) { _data[i, j] = buffer[k]; ++k; } } } #endregion GetSet #region Constructions public Array2D() { _row = 0; _col = 0; _data = null; } public Array2D(int row, int col) { if (row <= 0 || col <= 0) { throw new Exception("Dimension size must be positive!"); } _row = row; _col = col; _data = new Ty[row, col]; } #endregion Constructions #region SimpleOperations public Array2D<Ty> Add(Array2D<Ty> another) { int row = another.Row; int col = another.Col; if (row != _row || col != _col) { throw new Exception("Size must be the same!"); } Array2D<Ty> result = new Array2D<Ty>(row, col); Ty[,] A = _data; Ty[,] B = another.Data; Ty[,] R = result.Data; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { R[i, j] = BaseArithmetic.Add<Ty>(A[i, j], B[i, j]); } } return result; } public Array2D<Ty> Sub(Array2D<Ty> another) { int row = another.Row; int col = another.Col; if (row != _row || col != _col) { throw new Exception("Size must be the same!"); } Array2D<Ty> result = new Array2D<Ty>(row, col); Ty[,] A = _data; Ty[,] B = another.Data; Ty[,] R = result.Data; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { R[i, j] = BaseArithmetic.Sub<Ty>(A[i, j], B[i, j]); } } return result; } public Array2D<Ty> Mul(Array2D<Ty> another) { int row = another.Row; int col = another.Col; if (row != _row || col != _col) { throw new Exception("Size must be the same!"); } Array2D<Ty> result = new Array2D<Ty>(row, col); Ty[,] A = _data; Ty[,] B = another.Data; Ty[,] R = result.Data; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { R[i, j] = BaseArithmetic.Mul<Ty>(A[i, j], B[i, j]); } } return result; } public Array2D<Ty> Div(Array2D<Ty> another) { int row = another.Row; int col = another.Col; if (row != _row || col != _col) { throw new Exception("Size must be the same!"); } Array2D<Ty> result = new Array2D<Ty>(row, col); Ty[,] A = _data; Ty[,] B = another.Data; Ty[,] R = result.Data; for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { R[i, j] = BaseArithmetic.Div<Ty>(A[i, j], B[i, j]); } } return result; } public void FindMaxMin(out Ty max, out Ty min) { int ret = 0; Ty value; max = _data[0, 0]; min = _data[0, 0]; for (int i = 0; i < _row; ++i) { for (int j = 0; j < _col; ++j) { value = _data[i, j]; ret = BaseComparator<Ty>.Instance.Compare(value, max); if (ret >= 0) max = value; else { ret = BaseComparator<Ty>.Instance.Compare(value, min); if (ret < 0) min = value; } } } if (BaseComparator<Ty>.Instance.Compare(max, min) == 0) { throw new Exception("Max = Min"); } } #endregion SimpleOperations #region OverloadedOperations public static Array2D<Ty> operator +(Array2D<Ty> a, Array2D<Ty> b) { return a.Add(b); } public static Array2D<Ty> operator -(Array2D<Ty> a, Array2D<Ty> b) { return a.Sub(b); } public static Array2D<Ty> operator *(Array2D<Ty> a, Array2D<Ty> b) { return a.Mul(b); } public static Array2D<Ty> operator /(Array2D<Ty> a, Array2D<Ty> b) { return a.Div(b); } #endregion OverloadedOperations } public static class BaseArithmetic { private static string GetTypeString<Ty>(Ty t) where Ty : struct { string ts = typeof(Ty).ToString(); return ts.Substring(ts.LastIndexOf('.') + 1); } #region BasicOperations public static Ty Add<Ty>(Ty a, Ty b) where Ty : struct { string str = GetTypeString<Ty>(a); switch (str) { case "Int16": case "Int32": int result1 = Convert.ToInt32(a) + Convert.ToInt32(b); return (Ty)(Convert.ChangeType(result1, typeof(Ty))); case "Byte": case "UInt16": case "UInt32": uint result2 = Convert.ToUInt32(a) + Convert.ToUInt32(b); return (Ty)(Convert.ChangeType(result2, typeof(Ty))); case "Single": case "Double": double result3 = Convert.ToDouble(a) + Convert.ToDouble(b); return (Ty)(Convert.ChangeType(result3, typeof(Ty))); default: return (Ty)(new object()); } } public static Ty Sub<Ty>(Ty a, Ty b) where Ty : struct { string str = GetTypeString<Ty>(a); switch (str) { case "Int16": case "Int32": int result1 = Convert.ToInt32(a) - Convert.ToInt32(b); return (Ty)(Convert.ChangeType(result1, typeof(Ty))); case "Byte": case "UInt16": case "UInt32": uint result2 = Convert.ToUInt32(a) - Convert.ToUInt32(b); return (Ty)(Convert.ChangeType(result2, typeof(Ty))); case "Single": case "Double": double result3 = Convert.ToDouble(a) - Convert.ToDouble(b); return (Ty)(Convert.ChangeType(result3, typeof(Ty))); default: return (Ty)(new object()); } } public static Ty Mul<Ty>(Ty a, Ty b) where Ty : struct { string str = GetTypeString<Ty>(a); switch (str) { case "Int16": case "Int32": int result1 = Convert.ToInt32(a) * Convert.ToInt32(b); return (Ty)(Convert.ChangeType(result1, typeof(Ty))); case "Byte": case "UInt16": case "UInt32": uint result2 = Convert.ToUInt32(a) * Convert.ToUInt32(b); return (Ty)(Convert.ChangeType(result2, typeof(Ty))); case "Single": case "Double": double result3 = Convert.ToDouble(a) * Convert.ToDouble(b); return (Ty)(Convert.ChangeType(result3, typeof(Ty))); default: return (Ty)(new object()); } } public static Ty Div<Ty>(Ty a, Ty b) where Ty : struct { string str = GetTypeString<Ty>(a); switch (str) { case "Int16": case "Int32": int ib = Convert.ToInt32(b); if (ib == 0) throw new DivideByZeroException(); int result1 = Convert.ToInt32(a) / ib; return (Ty)(Convert.ChangeType(result1, typeof(Ty))); case "Byte": case "UInt16": case "UInt32": uint ub = Convert.ToUInt32(b); if (ub == 0) throw new DivideByZeroException(); uint result2 = Convert.ToUInt32(a) / ub; return (Ty)(Convert.ChangeType(result2, typeof(Ty))); case "Single": case "Double": double db = Convert.ToDouble(b); if (Math.Abs(db) < Double.Epsilon) throw new DivideByZeroException(); double result3 = Convert.ToDouble(a) / db; return (Ty)(Convert.ChangeType(result3, typeof(Ty))); default: return (Ty)(new object()); } } #endregion BasicOperations } public static class BaseConvertor { public static Array2D<byte> ToByteArray<Ty>(Array2D<Ty> src, out double scale, out double offset) where Ty : struct { int row = src.Row; int col = src.Col; Array2D<byte> dst = new Array2D<byte>(row, col); byte[,] dstData = dst.Data; Ty[,] srcData = src.Data; Ty max, min; src.FindMaxMin(out max, out min); scale = Convert.ToDouble(BaseArithmetic.Sub(max, min)) / 255; offset = Convert.ToDouble(min); for (int i = 0; i < row; ++i) { for (int j = 0; j < col; ++j) { dstData[i, j] = (byte)(Convert.ToDouble(BaseArithmetic.Sub(srcData[i, j], min)) / scale + 0.5); } } return dst; } } public class BaseComparator<Ty> { Comparison<Ty> _comparison; //比较委托 static readonly Dictionary<Type, Delegate> _map = new Dictionary<Type, Delegate>(); //实现单例 static readonly BaseComparator<Ty> _instance = new BaseComparator<Ty>(); private BaseComparator() { } public static BaseComparator<Ty> Instance { get { System.Diagnostics.Debug.Assert(_map.ContainsKey(typeof(Ty))); //强转为具体的比较委托 _instance._comparison = (Comparison<Ty>)_map[typeof(Ty)]; return _instance; } } //情态构造,初始化 static BaseComparator() { //基础类型比较器 Type t = typeof(Ty); if (t == typeof(Byte)) { Comparison<Byte> cmp_Byte = delegate(Byte t1, Byte t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(Byte), (Delegate)cmp_Byte); } else if(t==typeof(UInt16)) { Comparison<UInt16> cmp_UInt16 = delegate(UInt16 t1, UInt16 t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(UInt16), (Delegate)cmp_UInt16); } else if (t == typeof(Int16)) { Comparison<Int16> cmp_Int16 = delegate(Int16 t1, Int16 t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(Int16), (Delegate)cmp_Int16); } else if(t==typeof(UInt32)) { Comparison<UInt32> cmp_UInt32 = delegate(UInt32 t1, UInt32 t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(UInt32), (Delegate)cmp_UInt32); } else if(t==typeof(Int32)) { Comparison<Int32> cmp_Int32 = delegate(Int32 t1, Int32 t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(Int32), (Delegate)cmp_Int32); } else if (t == typeof(Single)) { Comparison<Single> cmp_Single = delegate(Single t1, Single t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(Single), (Delegate)cmp_Single); } else if (t == typeof(Double)) { Comparison<Double> cmp_Double = delegate(Double t1, Double t2) { return t1 > t2 ? 1 : (t1 == t2 ? 0 : -1); }; _map.Add(typeof(Double), (Delegate)cmp_Double); } else { throw new Exception("Unsupported type!"); } } //注册自定义比较 public static void Register<NewTy>(Comparison<NewTy> comparison) { System.Diagnostics.Debug.Assert(_map.ContainsKey(typeof(NewTy)) == false); _map.Add(typeof(NewTy), (Delegate)comparison); } //比较函数,以后用来实现IComparator用 public int Compare(Ty t1, Ty t2) { System.Diagnostics.Debug.Assert(_comparison != null); return _comparison(t1, t2); } } }
使用示例
Array2D<int> ia = new Array2D<int>(800, 800); for (int i = 0; i < 800; ++i) { for (int j = 0; j < 800; ++j) { ia.Data[i, j] = ((400 - i) * (400 - j)) % 400; } } double scale,offset; Array2D<byte> ba = BaseConvertor.ToByteArray(ia, out scale,out offset);
生成的二维数组转换成灰度图像如下
瞬间科技感了~~~
还可以这样
Array2D<int> ia = new Array2D<int>(800, 800); Array2D<int> ib = new Array2D<int>(800, 800); Random rnd = new Random(); for (int i = 0; i < 800; ++i) { for (int j = 0; j < 800; ++j) { ia.Data[i, j] = ((400 - i) * (400 - j)) % 400; //同上 ib.Data[i, j] =rnd.Next(-200,200); //随机噪声 } } Array2D<int> ic = ia - ib; // 重载了基本运算符(+,-,*,/) 用起来很方便了
添加噪声后的数组ic,现将其转换为byte数组
Array2D<byte> bc=BaseConvertor.ToByteArray(ic,scale,offset);将bc转换为灰度图如下
更加科技感了~~~
这个模板会用到个人的项目中,更多内容不便公开,待项目完成之后再公布。
如果不使用模板,那么针对每一种数据类型都要分别编写代码,
大量的重复工作,效率很低,因此建议使用泛型(Generics)和委托(Delegates).
LOG@ 2014/08/15 11:36 Fri. BJ
点此领取楼主 (本文全原创,转载请注明出处 http://blog.csdn.net/fengyhack)
相关文章推荐
- java 文件上传 与 把文件解析成一个字节数组简单的后台示例
- 一个超级简单的HTML模板框架源代码以及使用示例
- [VB.Net]委托的一个简单示例
- 类模板作为函数参数以及作为类模板参数的一个简单示例
- 一个简单的模板数组
- 一个简单的类模板的友元函数和友元类示例
- 一个简单的破解示例
- 使用委托数组的一个例子简介一下委托
- Delphi7下用dbExpress调用Oracle存储过程(返回数据集)的一个简单示例和调试过程
- Delphi7下用dbExpress调用Oracle存储过程(返回数据集)的一个简单示例和调试过程
- 一个Forms验证简单示例
- 一个C#实现的最简单的委托例子
- 一个C#实现的最简单的委托例子
- 一维数组的简单封装 carray模板。
- 一个序列化的简单示例
- SpringJdbc的一个简单示例
- Asp.net 2.0 一个简单的联动DropDownList示例(示例代码下载) [zhuan :D]
- HyperDAL 代码生成器 HyperDTT 一个模板示例
- 一个最简单的.NET Remoting构建的分布式应用程序示例
- 一个简单的wince.net流驱动模板