c# – 实现泛型方法处理不同整数类型集合的正确方法是什么?
发布时间:2020-12-15 21:52:46 所属栏目:百科 来源:网络整理
导读:我正在编写一种特殊的System.IO.BinaryWriter.本作者应该能够处理整数类型,包括枚举,以及这些类型的集合. abstract class MyBinaryWriter{ // ... #region Methods: Basic Types: Writing public abstract void Write(byte value); public abstract void Wri
我正在编写一种特殊的System.IO.BinaryWriter.本作者应该能够处理整数类型,包括枚举,以及这些类型的集合.
abstract class MyBinaryWriter { // ... #region Methods: Basic Types: Writing public abstract void Write(byte value); public abstract void Write(ushort value); public abstract void Write(uint value); public abstract void Write(ulong value); public abstract void Write(string value); #endregion #region Methods: Complex Types: Writing public virtual void Write<T>(ICollection<T> collection) { // first write the 32-bit-unsigned-length prefix if (collection == null || collection.Count == 0) { Write((uint)0); } else { Write((uint)collection.Count); // then write the elements,if any foreach (var item in collection) ; // What here? Obviously Write(item) doesn't work... } } // ... } 处理这个问题的最佳方法是什么?使用泛型比使用每个整数类型和我希望处理的每个枚举类型编写重载更好的解决方案?接下来是一个可能的解决方案,但我不太喜欢并且存在潜在的性能问题. #region Methods: Complex Types: Writing public virtual void Write<T>(ICollection<T> collection) where T : IConvertible { // first write the 32-bit-unsigned-length prefix if (collection == null || collection.Count == 0) { Write((uint)0); } else { Write((uint)collection.Count); // get the method for writing an element Action<T> write = null; var type = typeof(T); if (type.IsEnum) type = Enum.GetUnderlyingType(type); switch (Type.GetTypeCode(type)) { case TypeCode.Byte: case TypeCode.SByte: write = (x => Write((byte)(IConvertible)x.ToByte(null))); break; case TypeCode.Int16: case TypeCode.UInt16: write = (x => Write((ushort)(IConvertible)x.ToUInt16(null))); break; case TypeCode.Int32: case TypeCode.UInt32: write = (x => Write((uint)(IConvertible)x.ToUInt32(null))); break; case TypeCode.Int64: case TypeCode.UInt64: write = (x => Write((ulong)(IConvertible)x.ToUInt64(null))); break; default: Debug.Fail("Only supported for integral types."); break; } // then write the elements,if any foreach (var item in collection) write(item); } } 解决方法
一种方法是使用编译的表达式:
// helper classes which compiles a fast,type-safe delegate for writing various types static class MyBinaryWriterHelper<T> { public static readonly Action<MyBinaryWriter,T> WriteAction; // this initialization is a bit expensive,but it will occur only once // for each writable type T and will occur lazily static { // find the existing Write(T) on the MyBinaryWriter type var writeMethod = typeof(MyBinaryWriter).GetMethods() .FirstOrDefault(m => m.Name == "Write" && m.GetArguments().Length == 1 && m.GetArguments()[0](p => p.ParameterType == typeof(T) ); // if there is no such method,fail if (writeMethod == null) { throw ... } // build up an expression (writer,t) => writer.Write(t) var writerParam = Expression.Parameter(typeof(MyBinaryWriter)); var tParam = Expression.Parameter(typeof(T)); var call = Expression.Call(writerParam,writeMethod,tParam); var lambda = Expression.Lambda<Action<MyBinaryWriter,T>>(call,new[] { writerParam,tParam }); // compile the expression to a delegate,caching the result statically in the // readonly WriteAction field WriteAction = lambda.Compile(); } } // then in your writer class public void Write<T>(IEnumerable<T> collection) { // other collection writing logic (e. g. writing the count) ... // to write out the items,just use the static action field foreach (var t in collection) { MyBinaryWriterHelper<T>.WriteAction(this,t); } } 虽然没有办法使用泛型来强制类型为“数字”,但您可以使用IConvertible(如示例代码中)作为松散约束来实现此目的,以增加额外的编译时安全性. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- ExecuteNonQuery,ExecuteScalar,ExecuteReader的比较
- c# – 使用distinct和StringComparison.OrdinalIgnoreCase列
- 约束Dojo FloatingPane的位置
- AJAX入门基础
- 为什么我需要覆盖C#中的.Equals和GetHashCode
- 语言无关 – TDD测试是否应该首先失败?
- 正则表达式小记--入门到会写
- org.codehaus.jackson.annotate.JsonIgnore与com.fasterxml
- xcode – 链接被抬起..什么是-rpath? MacOS X.
- AJAX 跨域请求 - JSONP获取JSON数据