增加可空key的字典类型

This commit is contained in:
懒得勤快
2022-01-17 20:38:37 +08:00
parent 3c49e14326
commit 0ae435bf70
11 changed files with 299 additions and 17 deletions
@@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Masuit.Tools.Systems;
namespace Masuit.Tools
{
@@ -309,7 +310,7 @@ namespace Masuit.Tools
/// <param name="source"></param>
/// <param name="keySelector">键选择器</param>
/// <returns></returns>
public static Dictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
public static NullableDictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var dic = new Dictionary<TKey, TSource>();
foreach (var item in source)
@@ -330,9 +331,9 @@ namespace Masuit.Tools
/// <param name="keySelector">键选择器</param>
/// <param name="elementSelector">值选择器</param>
/// <returns></returns>
public static Dictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
public static NullableDictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
{
var dic = new Dictionary<TKey, TElement>();
var dic = new NullableDictionary<TKey, TElement>();
foreach (var item in source)
{
dic[keySelector(item)] = elementSelector(item);
@@ -351,9 +352,9 @@ namespace Masuit.Tools
/// <param name="keySelector">键选择器</param>
/// <param name="elementSelector">值选择器</param>
/// <returns></returns>
public static async Task<IDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToDictionarySafetyAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
{
var dic = new ConcurrentDictionary<TKey, TElement>();
var dic = new NullableConcurrentDictionary<TKey, TElement>();
await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
return dic;
}
@@ -367,9 +368,9 @@ namespace Masuit.Tools
/// <param name="source"></param>
/// <param name="keySelector">键选择器</param>
/// <returns></returns>
public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
public static NullableConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var dic = new ConcurrentDictionary<TKey, TSource>();
var dic = new NullableConcurrentDictionary<TKey, TSource>();
foreach (var item in source)
{
dic[keySelector(item)] = item;
@@ -388,9 +389,9 @@ namespace Masuit.Tools
/// <param name="keySelector">键选择器</param>
/// <param name="elementSelector">值选择器</param>
/// <returns></returns>
public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
public static NullableConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
{
var dic = new ConcurrentDictionary<TKey, TElement>();
var dic = new NullableConcurrentDictionary<TKey, TElement>();
foreach (var item in source)
{
dic[keySelector(item)] = elementSelector(item);
@@ -409,7 +410,7 @@ namespace Masuit.Tools
/// <param name="keySelector">键选择器</param>
/// <param name="elementSelector">值选择器</param>
/// <returns></returns>
public static async Task<ConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
public static async Task<NullableConcurrentDictionary<TKey, TElement>> ToConcurrentDictionaryAsync<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, Task<TElement>> elementSelector)
{
var dic = new ConcurrentDictionary<TKey, TElement>();
await source.ForeachAsync(async item => dic[keySelector(item)] = await elementSelector(item));
@@ -423,7 +424,7 @@ namespace Masuit.Tools
/// <typeparam name="TValue"></typeparam>
/// <param name="dic"></param>
/// <returns></returns>
public static ConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic) => new(dic);
public static NullableConcurrentDictionary<TKey, TValue> AsConcurrentDictionary<TKey, TValue>(this Dictionary<TKey, TValue> dic) => dic;
/// <summary>
/// 转换成普通字典集合
@@ -432,6 +433,6 @@ namespace Masuit.Tools
/// <typeparam name="TValue"></typeparam>
/// <param name="dic"></param>
/// <returns></returns>
public static Dictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic) => new(dic);
public static NullableDictionary<TKey, TValue> AsDictionary<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dic) => dic;
}
}
}
@@ -4,7 +4,7 @@
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CodeAnalysisRuleSet />
<Version>2.4.7.1</Version>
<Version>2.4.7.2</Version>
<Authors>懒得勤快</Authors>
<Description>Masuit.Tools基础公共库,包含一些常用的操作类,大都是静态类,加密解密,反射操作,Excel简单导出,权重随机筛选算法,分布式短id,表达式树,linq扩展,文件压缩,多线程下载和FTP客户端,硬件信息,字符串扩展方法,日期时间扩展操作,中国农历,大文件拷贝,图像裁剪,验证码,断点续传,集合扩展等常用封装。</Description>
<Copyright>懒得勤快,长空X</Copyright>
@@ -0,0 +1,104 @@
using System.ComponentModel;
namespace Masuit.Tools.Systems;
/// <summary>
/// 可空对象
/// </summary>
/// <typeparam name="T"></typeparam>
public readonly struct NullObject<T>
{
[DefaultValue(true)]
private readonly bool _isnull;
private NullObject(T item, bool isnull) : this()
{
_isnull = isnull;
Item = item;
}
public NullObject(T item) : this(item, item == null)
{
}
public static NullObject<T> Null()
{
return new NullObject<T>();
}
public T Item { get; }
/// <summary>
/// 是否是null
/// </summary>
/// <returns></returns>
public bool IsNull()
{
return _isnull;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="nullObject"></param>
public static implicit operator T(NullObject<T> nullObject)
{
return nullObject.Item;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="item"></param>
public static implicit operator NullObject<T>(T item)
{
return new NullObject<T>(item);
}
public override string ToString()
{
return (Item != null) ? Item.ToString() : "NULL";
}
public override bool Equals(object obj)
{
if (obj == null)
{
return IsNull();
}
if (obj is not NullObject<T> nullObject)
{
return false;
}
if (IsNull())
{
return nullObject.IsNull();
}
if (nullObject.IsNull())
{
return false;
}
return Item.Equals(nullObject.Item);
}
public override int GetHashCode()
{
if (_isnull)
{
return 0;
}
var result = Item.GetHashCode();
if (result >= 0)
{
result++;
}
return result;
}
}
@@ -0,0 +1,72 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Masuit.Tools.Systems;
/// <summary>
/// 支持null-key和value的字典类型
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class NullableConcurrentDictionary<TKey, TValue> : ConcurrentDictionary<NullObject<TKey>, TValue>
{
public NullableConcurrentDictionary() : base()
{
}
public NullableConcurrentDictionary(int concurrencyLevel, int capacity) : base(concurrencyLevel, capacity)
{
}
public NullableConcurrentDictionary(IEqualityComparer<NullObject<TKey>> comparer) : base(comparer)
{
}
public new TValue this[NullObject<TKey> key]
{
get => TryGetValue(key, out var value) ? value : default;
set => base[key] = value;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator NullableConcurrentDictionary<TKey, TValue>(Dictionary<TKey, TValue> dic)
{
var nullableDictionary = new NullableConcurrentDictionary<TKey, TValue>();
foreach (var p in dic)
{
nullableDictionary[p.Key] = p.Value;
}
return nullableDictionary;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator NullableConcurrentDictionary<TKey, TValue>(ConcurrentDictionary<TKey, TValue> dic)
{
var nullableDictionary = new NullableConcurrentDictionary<TKey, TValue>();
foreach (var p in dic)
{
nullableDictionary[p.Key] = p.Value;
}
return nullableDictionary;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator ConcurrentDictionary<TKey, TValue>(NullableConcurrentDictionary<TKey, TValue> dic)
{
var newdic = new ConcurrentDictionary<TKey, TValue>();
foreach (var p in dic)
{
newdic[p.Key] = p.Value;
}
return newdic;
}
}
@@ -0,0 +1,84 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace Masuit.Tools.Systems;
/// <summary>
/// 支持null-key和value的字典类型
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class NullableDictionary<TKey, TValue> : Dictionary<NullObject<TKey>, TValue>
{
public NullableDictionary() : base()
{
}
public NullableDictionary(int capacity) : base(capacity)
{
}
public NullableDictionary(IEqualityComparer<NullObject<TKey>>? comparer) : base(comparer)
{
}
public NullableDictionary(int capacity, IEqualityComparer<NullObject<TKey>> comparer) : base(capacity, comparer)
{
}
public NullableDictionary(IDictionary<NullObject<TKey>, TValue> dictionary) : base(dictionary)
{
}
public NullableDictionary(IDictionary<NullObject<TKey>, TValue> dictionary, IEqualityComparer<NullObject<TKey>> comparer) : base(dictionary, comparer)
{
}
public new TValue this[NullObject<TKey> key]
{
get => TryGetValue(key, out var value) ? value : default;
set => base[key] = value;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator NullableDictionary<TKey, TValue>(Dictionary<TKey, TValue> dic)
{
var nullableDictionary = new NullableDictionary<TKey, TValue>();
foreach (var p in dic)
{
nullableDictionary[p.Key] = p.Value;
}
return nullableDictionary;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator NullableDictionary<TKey, TValue>(ConcurrentDictionary<TKey, TValue> dic)
{
var nullableDictionary = new NullableDictionary<TKey, TValue>();
foreach (var p in dic)
{
nullableDictionary[p.Key] = p.Value;
}
return nullableDictionary;
}
/// <summary>
/// 隐式转换
/// </summary>
/// <param name="dic"></param>
public static implicit operator Dictionary<TKey, TValue>(NullableDictionary<TKey, TValue> dic)
{
var newdic = new Dictionary<TKey, TValue>();
foreach (var p in dic)
{
newdic[p.Key] = p.Value;
}
return newdic;
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ github:https://github.com/ldqk/Masuit.Tools
<UserSecretsId>830c282f-f7c1-42be-8651-4cd06ac8e73f</UserSecretsId>
<RepositoryType>Github</RepositoryType>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Version>2.4.7.1</Version>
<Version>2.4.7.2</Version>
<FileVersion>2.4.5.6</FileVersion>
<Company>masuit.com</Company>
<AssemblyVersion>2.4.5.6</AssemblyVersion>
@@ -277,6 +277,15 @@
<Compile Include="..\Masuit.Tools.Abstractions\Systems\LimitedQueue.cs">
<Link>Systems\LimitedQueue.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullableConcurrentDictionary.cs">
<Link>Systems\NullableConcurrentDictionary.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullableDictionary.cs">
<Link>Systems\NullableDictionary.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullObject.cs">
<Link>Systems\NullObject.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\SnowFlake.cs">
<Link>Systems\SnowFlake.cs</Link>
</Compile>
+1 -1
View File
@@ -4,7 +4,7 @@
<!--*-->
<id>Masuit.Tools.Net45</id>
<!--*-->
<version>2.4.7.1</version>
<version>2.4.7.2</version>
<title>Masuit.Tools</title>
<!--*-->
<authors>懒得勤快</authors>
+9
View File
@@ -112,6 +112,15 @@
<Compile Include="..\Masuit.Tools.Abstractions\Systems\*.*">
<Link>Systems\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullableConcurrentDictionary.cs">
<Link>Systems\NullableConcurrentDictionary.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullableDictionary.cs">
<Link>Systems\NullableDictionary.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Systems\NullObject.cs">
<Link>Systems\NullObject.cs</Link>
</Compile>
<Compile Include="..\Masuit.Tools.Abstractions\Validator\*.*">
<Link>Validator\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
+1 -1
View File
@@ -4,7 +4,7 @@
<!--*-->
<id>Masuit.Tools.Net</id>
<!--*-->
<version>2.4.7.1</version>
<version>2.4.7.2</version>
<title>Masuit.Tools</title>
<!--*-->
<authors>懒得勤快</authors>
+3
View File
@@ -800,6 +800,9 @@ public class ClassDto
}
```
### 49. 可空key的字典类型
NullableConcurrentDictionary和NullableDictionary
用法和普通的字典类型保持一致,相比于普通的字典类型,其key是可以为null的,并且索引器获取时,如果key不存在,是不会报错的,会get到value类型的默认值。
# Asp.Net MVC和Asp.Net Core的支持断点续传和多线程下载的ResumeFileResult