You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让PowerShell自动识别自定义Hashtable子类的重载运算符

让PowerShell自动识别自定义Hashtable子类的重载运算符

1. C#自定义Hashtable子类实现

public class CustomHashtable : Hashtable
{
    public CustomHashtable() : base() { }
    
    public CustomHashtable(Hashtable a) : base(a) {}

    public string GetFoo()
    {
        return "bar";
    }

    public static CustomHashtable operator +(CustomHashtable a, Hashtable b)
    {
        foreach (DictionaryEntry entry in b)
        {
            a.Add(entry.Key, entry.Value + "z");
        }

        return a;
    }
}

2. C#环境下的正常运行效果

在C#控制台应用中,该子类的重载运算符可正常调用,且变量类型始终保持为CustomHashtable:

var ch = new CustomHashtable(new Hashtable(){
    { "Age", 54 }
});

ch += new Hashtable(){
    { "LastName", "Jobs" },
    { "FirstName",  "Steve"}
};

System.Console.WriteLine(ch.GetType()); // 输出:CustomHashtable
System.Console.WriteLine(ch.GetFoo()); // 输出:bar

3. PowerShell中的问题

将编译后的DLL导入PowerShell后,直接使用+=运算符会导致变量类型被隐式转换为基类System.Collections.Hashtable,进而无法调用自定义方法GetFoo():

Import-Module "$PSScriptRoot/CustomHashtable.dll"

$Hash = [CustomHashtable]::New(@{
    Foo = 'Bar';
})

$Hash += @{
    Name = 'Toot';
}

$Hash.GetFoo()

报错信息:

Line |
  18 |  $Hash.GetFoo()
     |  ~~~~~~~~~~~~~~
     | Method invocation failed because [System.Collections.Hashtable] does not contain a method named 'GetFoo'

临时解决办法是显式强制类型转换,但使用繁琐:

Import-Module "$PSScriptRoot/CustomHashtable.dll"

$Hash = [CustomHashtable]::New(@{
    Foo = 'Bar';
})

[CustomHashtable]$Hash += @{
    Name = 'Toot';
}

$Hash.GetFoo() # 输出:bar

4. 解决方案

要让PowerShell自动识别自定义重载运算符,可通过以下方式优化:

4.1 调整运算符重载的参数类型

PowerShell的哈希表字面量@{}本质是Hashtable,但PowerShell在匹配运算符时会优先选择更通用的类型定义。将运算符的第二个参数改为IDictionary接口(Hashtable实现了该接口),能让PowerShell精准匹配到自定义运算符:

public static CustomHashtable operator +(CustomHashtable a, IDictionary b)
{
    foreach (DictionaryEntry entry in b)
    {
        a.Add(entry.Key, entry.Value + "z");
    }

    return a;
}

4.2 替代方案:添加显式方法

如果不想修改运算符定义,可为自定义类添加AddRange方法,直接调用方法而非依赖运算符,避免类型转换问题:

public void AddRange(IDictionary entries)
{
    foreach (DictionaryEntry entry in entries)
    {
        this.Add(entry.Key, entry.Value + "z");
    }
}

PowerShell中调用方式:

$Hash.AddRange(@{ Name = 'Toot' })

关键原因说明

PowerShell的+=运算符处理逻辑会优先尝试基类的默认行为,当自定义运算符的参数类型匹配度不足时,会将结果隐式转换为基类Hashtable,丢失自定义类型的方法。使用更通用的接口作为参数,能让PowerShell优先触发自定义运算符,保留原类型。

内容的提问来源于stack exchange,提问作者soulshined

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:58:10