如何让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
相关产品推荐
相关产品推荐

