.NET避免裝箱的方法
.NET提供struct類型,正確使用可以減少對象數(shù)量,從而降低GC壓力,提高性能。不過有時候我會發(fā)現(xiàn),某些同學有這方面的意識,但是有時候一疏忽一偷懶,就沒有得到相應的效果了。這里舉一個真實的例子:假設我們要將一對int作為字典的鍵,用于映射到某些數(shù)據(jù),那么你會怎么做?當然我們可以直接使用Tuple<int, int>,但這樣就可能產(chǎn)生大量的對象。于是我們打算使用自定義的值類型:
private struct MyKey {
private readonly int _a;
private readonly int _b;
public MyKey(int a, int b) {
_a = a;
_b = b;
}
}這么做正確嗎?假如你做一下測試,會發(fā)現(xiàn)它已經(jīng)可以“正確使用”了,但實際上還是錯誤的。我們用它來做字典的鍵,會依賴GetHashCode和Equals兩個方法,由于MyKey沒有提供這兩個方法,就會自動使用System.ValueType里的實現(xiàn),這便引起了裝箱。
好吧,那么我們就來實現(xiàn)一下:
private struct MyKey {
// ...
public override int GetHashCode() {
// ...
}
public override bool Equals(object that) {
// ...
}
}那么現(xiàn)在呢?可能現(xiàn)在您就會比較容易意識到,即便GetHashCode已經(jīng)沒有問題了,但是Equals方法還是會引起裝箱,因為that參數(shù)依然是object類型。
怎么破?當然有辦法,因為像HashSet<T>或是Dictionary<TKey, TValue>集合其實都不會直接調(diào)用GetHashCode和Equals方法,都是通過一個IEqualityComparer<T>對象來委托調(diào)用的:
public interface IEqualityComparer<in T> {
bool Equals(T x, T y);
int GetHashCode(T obj);
}假如在創(chuàng)建集合的時候沒有提供比較器,則會使用默認的EqualityComparer<T>.Default對象,它的構造方法是這樣的:
private static EqualityComparer<T> CreateComparer<T>() {
Contract.Ensures(Contract.Result<EqualityComparer<T>>() != null);
RuntimeType t = (RuntimeType)typeof(T);
// Specialize type byte for performance reasons
if (t == typeof(byte)) {
return (EqualityComparer<T>)(object)(new ByteEqualityComparer());
}
// If T implements IEquatable<T> return a GenericEqualityComparer<T>
if (typeof(IEquatable<T>).IsAssignableFrom(t)) {
return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter(
(RuntimeType)typeof(GenericEqualityComparer<int>), t);
}
// If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) {
return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter(
(RuntimeType)typeof(NullableEqualityComparer<int>), u);
}
}
// If T is an int-based Enum, return an EnumEqualityComparer<T>
// See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
if (t.IsEnum && Enum.GetUnderlyingType(t) == typeof(int)) {
return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter(
(RuntimeType)typeof(EnumEqualityComparer<int>), t);
}
// Otherwise return an ObjectEqualityComparer<T>
return new ObjectEqualityComparer<T>();
}可以看出,根據(jù)不同的情況它會使用各式不同的比較器。其中最適合我們的自然就是實現(xiàn)IEquatable<T>接口的分支了。于是我們可以這么做:
struct MyKey : IEquatable<MyKey> {
// ...
public bool Equals(MyKey that) {
// ...
}
}這才是最終符合我們要求的做法。
以上所述是小編給大家介紹的.NET避免裝箱的方法,希望對大家有所幫助。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關文章
asp.net下比較兩個等長字符串是否含有完全相同字符(忽略字符順序)
項目中遇到一個好玩的問題,需要比較兩個選擇區(qū)域選擇的文字是否一樣,就想到將這兩個區(qū)域中選中的文字鏈接起來進行兩個字符串之間的比較2010-06-06
ASP.NET MVC 中實現(xiàn)基于角色的權限控制的處理方法
在ASP.NET MVC中,通過使用其所提供的內(nèi)置2013-03-03
.NET Framework常用ORM框架iBatis.Net操作數(shù)據(jù)庫的方法
iBatis.Net 是一個輕量級的 ORM 框架,它允許開發(fā)者通過直接編寫 SQL 查詢來操作數(shù)據(jù)庫,并將查詢結果映射到對象模型中,本文將通過實際的代碼示例,詳細介紹如何在 .NET 環(huán)境中使用 iBatis.Net 進行數(shù)據(jù)庫操作,感興趣的朋友一起看看吧2024-08-08
ASP.NET連接數(shù)據(jù)庫并獲取數(shù)據(jù)方法總結
這篇文章主要介紹了ASP.NET連接數(shù)據(jù)庫并獲取數(shù)據(jù)方法,結合實例分析總結了ASP.NET連接數(shù)據(jù)庫及獲取數(shù)據(jù)的相關實現(xiàn)技巧,并附帶了web.config配置文件的使用方法與相關注意事項,需要的朋友可以參考下2015-11-11
.net+FusionChart實現(xiàn)動態(tài)顯示的柱狀圖和餅狀圖
這篇文章介紹了.net+FusionChart實現(xiàn)動態(tài)顯示柱狀圖和餅狀圖的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
詳解ASP.NET Core 中基于工廠的中間件激活的實現(xiàn)方法
這篇文章主要介紹了ASP.NET Core 中基于工廠的中間件激活的實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11

