Skip to content

Commit

Permalink
增加可空key的字典类型
Browse files Browse the repository at this point in the history
  • Loading branch information
ldqk committed Jan 17, 2022
1 parent 3c49e14 commit 0ae435b
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Masuit.Tools.Systems;

namespace Masuit.Tools
{
Expand Down Expand Up @@ -309,7 +310,7 @@ public static Task ForEachAsync<TKey, TValue>(this IDictionary<TKey, TValue> dic
/// <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)
Expand All @@ -330,9 +331,9 @@ public static Dictionary<TKey, TSource> ToDictionarySafety<TSource, TKey>(this I
/// <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);
Expand All @@ -351,9 +352,9 @@ public static Dictionary<TKey, TElement> ToDictionarySafety<TSource, TKey, TElem
/// <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;
}
Expand All @@ -367,9 +368,9 @@ public static async Task<IDictionary<TKey, TElement>> ToDictionarySafetyAsync<TS
/// <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;
Expand All @@ -388,9 +389,9 @@ public static ConcurrentDictionary<TKey, TSource> ToConcurrentDictionary<TSource
/// <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);
Expand All @@ -409,7 +410,7 @@ public static ConcurrentDictionary<TKey, TElement> ToConcurrentDictionary<TSourc
/// <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));
Expand All @@ -423,7 +424,7 @@ public static async Task<ConcurrentDictionary<TKey, TElement>> ToConcurrentDicti
/// <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>
/// 转换成普通字典集合
Expand All @@ -432,6 +433,6 @@ public static async Task<ConcurrentDictionary<TKey, TElement>> ToConcurrentDicti
/// <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;
}
}
}
2 changes: 1 addition & 1 deletion Masuit.Tools.Abstractions/Masuit.Tools.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
104 changes: 104 additions & 0 deletions Masuit.Tools.Abstractions/Systems/NullObject.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
72 changes: 72 additions & 0 deletions Masuit.Tools.Abstractions/Systems/NullableConcurrentDictionary.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
84 changes: 84 additions & 0 deletions Masuit.Tools.Abstractions/Systems/NullableDictionary.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
2 changes: 1 addition & 1 deletion Masuit.Tools.Core/Masuit.Tools.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
9 changes: 9 additions & 0 deletions Masuit.Tools.Net45/Masuit.Tools.Net45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion Masuit.Tools.Net45/package.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Loading

0 comments on commit 0ae435b

Please sign in to comment.