mirror of
https://github.com/ldqk/Masuit.Tools.git
synced 2026-10-29 12:43:16 +08:00
增加可空key的字典类型
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user