Проблема здесь в том, что [System.Tuple]::Create($a,$b)
не на самом деле создает экземпляр [System.Tuple]
, но [System.Tuple[T1,T2]]
, где T1
- это тип $a
, а T2
это тип $b
.
Несмотря на то, что они разделяют часть имени, [System.Tuple[T1,T2]]
- это , который нельзя назначить на [System.Tuple]
, поэтому нам нужно найти другой аргумент типа для ваш [HashSet]
.
Поскольку значения вашего элемента кортежа являются строками, go с [System.Tuple[string,string]]
:
$set = [System.Collections.Generic.HashSet[System.Tuple[string,string]]]::new()
$tuple = [System.Tuple]::Create("Hello", "World")
$set.Add($tuple)
ОТВЕТ НА БОНУС
Если вы go в другом Направление и просто создайте HashSet[object]
для максимально возможной присваиваемости, вы можете создать потокобезопасный ConcurrentSet
, обернув HashSet[object]
методы, которые вам нужно выставить в пользовательский класс powershell, а затем использовать ReaderWriteLockSlim
для облегчения одновременные чтения, но эксклюзивные записи:
using namespace System.Collections.Concurrent
using namespace System.Collections.Generic
using namespace System.Threading
# Custom IEqualityComparer based on [scriptblock]
# Use [PSComparer]::new({$args[0].Equals($args[1])}) to "restore" default comparer logic
class PSComparer : IEqualityComparer[object]
{
[scriptblock]
$Comparer
PSComparer()
{
$this.Comparer = {$args[0] -eq $args[1]}
}
PSComparer([scriptblock]$comparer)
{
$this.Comparer = $comparer
}
[bool]
Equals($a,$b)
{
return & $this.Comparer $a $b
}
[int]
GetHashCode($obj)
{
if($obj -is [object]){
return $obj.GetHashCode()
}
throw [System.ArgumentNullException]::new('obj')
}
}
class ConcurrentSet : IDisposable
{
hidden [ReaderWriterLockSlim]
$_lock
hidden [HashSet[object]]
$_set
ConcurrentSet()
{
# Default to PowerShell comparison logic, ie. `"1" -eq 1`
$this.Initialize([PSComparer]::new())
}
ConcurrentSet([IEqualityComparer[object]]$comparer)
{
$this.Initialize($comparer)
}
hidden
Initialize([IEqualityComparer[object]]$comparer)
{
$this._set = [HashSet[object]]::new($comparer)
$this._lock = [System.Threading.ReaderWriterLockSlim]::new()
}
[bool]
Add([object]$item)
{
$this._lock.EnterWriteLock()
try{
return $this._set.Add($item)
}
finally{
$this._lock.ExitWriteLock()
}
}
[bool]
Contains([object]$item)
{
$this._lock.EnterReadLock()
try{
return $this._set.Contains($item)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
Remove([object]$item)
{
$this._lock.EnterUpgradeableReadLock()
try{
if($this._set.Contains($item)){
$this._lock.EnterWriteLock()
try {
return $this._set.Remove($item)
}
finally {
$this._lock.ExitWriteLock()
}
}
return $false
}
finally{
$this._lock.ExitUpgradeableReadLock()
}
}
UnionWith([IEnumerable[object]]$other)
{
$this._lock.EnterWriteLock()
try{
$this._set.UnionWith($other)
}
finally{
$this._lock.ExitWriteLock()
}
}
IntersectWith([IEnumerable[object]]$other)
{
$this._lock.EnterWriteLock()
try{
$this._set.IntersectWith($other)
}
finally{
$this._lock.ExitWriteLock()
}
}
ExceptWith([IEnumerable[object]]$other)
{
$this._lock.EnterWriteLock()
try{
$this._set.ExceptWith($other)
}
finally{
$this._lock.ExitWriteLock()
}
}
SymmetricExceptWith([IEnumerable[object]]$other)
{
$this._lock.EnterWriteLock()
try{
$this._set.SymmetricExceptWith($other)
}
finally{
$this._lock.ExitWriteLock()
}
}
[bool]
IsSubsetOf([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.IsSubsetOf($other)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
IsSupersetOf([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.IsSupersetOf($other)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
IsProperSubsetOf([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.IsProperSubsetOf($other)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
IsProperSupersetOf([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.IsProperSupersetOf($other)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
Overlaps([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.Overlaps($other)
}
finally{
$this._lock.ExitReadLock()
}
}
[bool]
SetEquals([IEnumerable[object]]$other)
{
$this._lock.EnterReadLock()
try{
return $this._set.SetEquals($other)
}
finally{
$this._lock.ExitReadLock()
}
}
hidden [int]
get_Count()
{
return $this._set.Count
}
Dispose()
{
if($this._lock -is [System.IDisposable])
{
$this._lock.Dispose()
}
}
}