[.NET] : CastingEnumerable
前言 :
寫程式難免,會遇到要使用自訂函式來作物件陣列轉型。
寫了一個物件來做這個動作,跟大家分享。
說明 :
這個物件的特點為:
1. 使用到才轉型。不會在記憶體,建立整個轉型後的陣列副本。
2. 可在轉型時加入參數。
使用範例 :
namespace CLK.Collections.ConsoleApplication
{
public class User
{
public string LastName = string.Empty;
public string FirstName = string.Empty;
}
public class Data
{
public string DisplayName = string.Empty;
}
class Program
{
static void Main(string[] args)
{
User[] userArray = new User[2];
userArray[0] = new User();
userArray[0].LastName = "Chou";
userArray[0].FirstName = "Clark";
userArray[1] = new User();
userArray[1].LastName = "AAAA";
userArray[1].FirstName = "BBBBB";
IEnumerable<Data> dataList = CreateDataList(userArray, "★★★★★");
foreach (Data data in dataList)
{
Console.WriteLine(data.DisplayName);
}
Console.WriteLine("");
Console.WriteLine("End");
Console.ReadLine();
}
static IEnumerable<Data> CreateDataList(IEnumerable<User> userList, string decorator)
{
return new CastingEnumerable<Data, User>(userList, delegate(User user) { return CreateData(user, decorator); });
}
static Data CreateData(User user, string decorator)
{
Data data = new Data();
data.DisplayName = decorator + user.LastName + "." + user.FirstName + decorator;
return data;
}
}
}
程式碼 :
namespace CLK.Collections
{
public class CastingEnumerable<TResult, TSource> : IEnumerable<TResult>
{
//Properties
private readonly IEnumerable<TSource> _sourceEnumerable;
private CastingEnumerableDelegate<TResult, TSource> _enumerableDelegate;
// Construction
public CastingEnumerable(IEnumerable<TSource> sourceEnumerable, CastingEnumerableDelegate<TResult, TSource> enumerableDelegate)
{
#region Require
if (sourceEnumerable == null) throw new ArgumentNullException();
if (enumerableDelegate == null) throw new ArgumentNullException();
#endregion
_sourceEnumerable = sourceEnumerable;
_enumerableDelegate = enumerableDelegate;
}
// Member
public IEnumerator<TResult> GetEnumerator()
{
return new CastingEnumerator<TResult, TSource>(_sourceEnumerable.GetEnumerator(), _enumerableDelegate);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
namespace CLK.Collections
{
public class CastingEnumerator<TResult, TSource> : IEnumerator<TResult>
{
//Properties
private readonly IEnumerator<TSource> _sourceEnumerator;
private readonly CastingEnumerableDelegate<TResult, TSource> _enumerableDelegate;
private TResult _currentResult = default(TResult);
// Construction
public CastingEnumerator(IEnumerator<TSource> sourceEnumerator, CastingEnumerableDelegate<TResult, TSource> enumerableDelegate)
{
#region Require
if (sourceEnumerator == null) throw new ArgumentNullException();
if (enumerableDelegate == null) throw new ArgumentNullException();
#endregion
_sourceEnumerator = sourceEnumerator;
_enumerableDelegate = enumerableDelegate;
}
public virtual void Dispose()
{
_sourceEnumerator.Dispose();
_currentResult = default(TResult);
}
// Member
public TResult Current
{
get
{
return _currentResult;
}
}
object System.Collections.IEnumerator.Current
{
get
{
return this.Current;
}
}
public bool MoveNext()
{
if (_sourceEnumerator.MoveNext() == true)
{
_currentResult = _enumerableDelegate(_sourceEnumerator.Current);
return true;
}
return false;
}
public void Reset()
{
_sourceEnumerator.Reset();
_currentResult = default(TResult);
}
}
}
public delegate TResult CastingEnumerableDelegate<TResult, TSource>(TSource source);
相關資料 :
http://stackoverflow.com/questions/504729/how-do-i-cast-a-listt-effectively
http://msdn.microsoft.com/zh-tw/library/0yw3tz5k.aspx
簽名檔
期許自己能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。