網站首頁 編程語言 正文
.NET提供struct類型,正確使用可以減少對象數量,從而降低GC壓力,提高性能。不過有時候我會發現,某些同學有這方面的意識,但是有時候一疏忽一偷懶,就沒有得到相應的效果了。這里舉一個真實的例子:假設我們要將一對int
作為字典的鍵,用于映射到某些數據,那么你會怎么做?當然我們可以直接使用Tuple
,但這樣就可能產生大量的對象。于是我們打算使用自定義的值類型:
private struct MyKey { private readonly int _a; private readonly int _b; public MyKey(int a, int b) { _a = a; _b = b; } }
這么做正確嗎?假如你做一下測試,會發現它已經可以“正確使用”了,但實際上還是錯誤的。我們用它來做字典的鍵,會依賴GetHashCode
和Equals
兩個方法,由于MyKey
沒有提供這兩個方法,就會自動使用System.ValueType
里的實現,這便引起了裝箱。
好吧,那么我們就來實現一下:
private struct MyKey { // ... public override int GetHashCode() { // ... } public override bool Equals(object that) { // ... } }
那么現在呢?可能現在您就會比較容易意識到,即便GetHashCode
已經沒有問題了,但是Equals
方法還是會引起裝箱,因為that
參數依然是object
類型。
怎么破?當然有辦法,因為像HashSet
或是Dictionary
集合其實都不會直接調用GetHashCode
和Equals
方法,都是通過一個IEqualityComparer
對象來委托調用的:
public interface IEqualityComparer{ bool Equals(T x, T y); int GetHashCode(T obj); }
假如在創建集合的時候沒有提供比較器,則會使用默認的EqualityComparer
對象,它的構造方法是這樣的:
private static EqualityComparerCreateComparer () { Contract.Ensures(Contract.Result >() != null); RuntimeType t = (RuntimeType)typeof(T); // Specialize type byte for performance reasons if (t == typeof(byte)) { return (EqualityComparer )(object)(new ByteEqualityComparer()); } // If T implements IEquatable return a GenericEqualityComparer if (typeof(IEquatable ).IsAssignableFrom(t)) { return (EqualityComparer )RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter( (RuntimeType)typeof(GenericEqualityComparer ), t); } // If T is a Nullable where U implements IEquatable return a NullableEqualityComparer if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { RuntimeType u = (RuntimeType)t.GetGenericArguments()[0]; if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) { return (EqualityComparer )RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter( (RuntimeType)typeof(NullableEqualityComparer ), u); } } // If T is an int-based Enum, return an EnumEqualityComparer // 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 )RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter( (RuntimeType)typeof(EnumEqualityComparer ), t); } // Otherwise return an ObjectEqualityComparer return new ObjectEqualityComparer (); }
可以看出,根據不同的情況它會使用各式不同的比較器。其中最適合我們的自然就是實現IEquatable
接口的分支了。于是我們可以這么做:
struct MyKey : IEquatable{ // ... public bool Equals(MyKey that) { // ... } }
這才是最終符合我們要求的做法。
原文鏈接:http://blog.zhaojie.me/2013/04/dont-go-half-way-of-preventing-boxing.html
相關推薦
- 2022-03-30 Android實現靜音檢測功能_Android
- 2022-06-22 一文搞懂C++多態的用法_C 語言
- 2022-08-27 python中DataFrame數據合并merge()和concat()方法詳解_python
- 2023-06-04 Pandas中MultiIndex選擇并提取任何行和列_python
- 2023-02-18 Flow轉LiveData數據丟失原理詳解_Android
- 2022-05-09 Entity?Framework導航屬性介紹_實用技巧
- 2022-08-02 Python+Selenium實現瀏覽器標簽頁的切換_python
- 2023-06-13 C語言中函數返回值不一致問題_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支