本文介绍了PowerShell IComparable与子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下3个类:

Let's assume we have these 3 classes:

Class BaseClass : System.IComparable
{
    [int] $Value
    BaseClass([int] $v)
    {
        $this.Value = $v
    }
    [int] CompareTo($that)
    {
        If (-Not($that -is [BaseClass])) {
            Throw "Not comparable!!"
        }
        return $this.Value - $that.Value
    }
}
Class SubClassA : BaseClass
{
    SubClassA([int] $v) : base($v)
    {
    }
}
Class SubClassB : BaseClass
{
    SubClassB([int] $v) : base($v)
    {
    }
}

当我们比较BaseClass的实例时,此实现效果很好:

This implementation works great when we compare instances of BaseClass:

$base1 = [BaseClass]::new(1)
$base2 = [BaseClass]::new(2)
Write-Output ($base1 -lt $base2)
# Output: True
Write-Output ($base1 -gt $base2)
# Output: False

但是我找不到比较两个子类的两个实例的方法:

But I can't find a way to compare two instances of the two subclasses:

$subA1 = [SubClassA]::new(1)
$subB2 = [SubClassB]::new(2)
Write-Output (([BaseClass]$subA1) -lt ([BaseClass]$subB2))

PowerShell无法执行此代码,并引发以下错误:

PowerShell can't execute this code, throwing this error:

Impossibile confrontare "SubClassA" con "SubClassB".
Errore:
    "Impossibile convertire il valore "SubClassB" di tipo "SubClassB" nel tipo "SubClassA"."

从意大利语翻译成英语,此错误消息听起来像:

Translated from Italian to English, this error message sounds like:

Unable to compare "SubClassA" with "SubClassB".
Error:
    "Unable to convert the value "SubClassB" of type "SubClassB" to the type "SubClassA"."

为什么会出现此错误?如何将SubClassA的实例与SubClassB的实例进行比较,就好像它们是BaseClass的两个实例一样?

Why this error?How can we compare an instance of SubClassA with an instance of SubClassB as if they were two instances of BaseClass?

PS:$PSVersionTable的输出:

PSVersion                      5.1.17134.1
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17134.1
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

推荐答案

该行为的确令人惊讶,我发现您已打开一个GitHub问题进行讨论.

The behavior is indeed surprising and I see that you've opened a GitHub issue to discuss it.

一些其他想法:

  • PowerShell的运算符通常具有扩展的语义,通常不应假定它们在所有情况下都与C#对应语言一样工作-但是,在这种特定情况下,他们显然应该(请参见下文) ).

  • PowerShell's operators often have extended semantics and generally shouldn't be assumed to work the same as their C# counterparts in all cases - however, in this particular case they clearly should (see below).

-lt实际上可以与 base-class 实例一起使用的事实已经指出了一个区别:等效的C#类将另外需要<和运算符,以支持使用<.

The fact that -lt actually works with the base-class instances already points to a difference: the equivalent C# class would additionally require explicit overloading of the < and > operators in order to support to support use of <.

接口实现由PowerShell和C#中的派生类继承,因此为了应用-lt,无需强制转换为基类.

Interface implementations are inherited by derived classes in both PowerShell and C#, so there should be no need to cast to the base class in order to apply -lt.

这里似乎正在发生的事情是,PowerShell盲目地尝试将RHS转换为LHS的类型,而不考虑它们的共享基类.

What seems to be happening here is that PowerShell blindly tries to convert the RHS to the type of the LHS without considering their shared base class.

如果RHS类型直接从LHS类型派生(但不是相反),则不会出现此问题;例如:

The problem does not arise if the RHS type directly derives from the LHS type (but not the other way around); e.g.:

$base1 -lt $subA1  # OK: SubClassA (RHS) derives from BaseClass (LHS) 

$subA1 -lt $base1  # !! BREAKS: BaseClass (RHS) does NOT derive from SubClassA (LHS)

这篇关于PowerShell IComparable与子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 04:32