Skip to content

Implementing IConvertible prevents casting to string #11917

@alx9r

Description

@alx9r

Beginning sometime after PowerShell 5.1 a class implementing IConvertible throws an exception when casting to a string.

Note that in the repro below simply removing : IConvertible is sufficient to restore the ability to cast to string.

Steps to reproduce

//type.cs
using System;
public class C : IConvertible
{
    public readonly string Value = null;
    public C(string v) { Value = v; }
    override public String ToString() {return Value; }

    public TypeCode GetTypeCode() { return Value.GetTypeCode(); }
    public object   ToType(Type conversionType, IFormatProvider provider) { return ((IConvertible)Value).ToType(conversionType, provider); }
    public bool     ToBoolean(IFormatProvider provider)  { return ((IConvertible)Value).ToBoolean(provider); }
    public byte     ToByte(IFormatProvider provider)     { return ((IConvertible)Value).ToByte(provider); }
    public char     ToChar(IFormatProvider provider)     { return ((IConvertible)Value).ToChar(provider); }
    public DateTime ToDateTime(IFormatProvider provider) { return ((IConvertible)Value).ToDateTime(provider); }
    public decimal  ToDecimal(IFormatProvider provider)  { return ((IConvertible)Value).ToDecimal(provider); }
    public double   ToDouble(IFormatProvider provider)   { return ((IConvertible)Value).ToDouble(provider); }
    public short    ToInt16(IFormatProvider provider)    { return ((IConvertible)Value).ToInt16(provider); }
    public int      ToInt32(IFormatProvider provider)    { return ((IConvertible)Value).ToInt32(provider); }
    public long     ToInt64(IFormatProvider provider)    { return ((IConvertible)Value).ToInt64(provider); }
    public sbyte    ToSByte(IFormatProvider provider)    { return ((IConvertible)Value).ToSByte(provider); }
    public float    ToSingle(IFormatProvider provider)   { return ((IConvertible)Value).ToSingle(provider); }
    public string   ToString(IFormatProvider provider)   { return Value.ToString(provider); }
    public ushort   ToUInt16(IFormatProvider provider)   { return ((IConvertible)Value).ToUInt16(provider); }
    public uint     ToUInt32(IFormatProvider provider)   { return ((IConvertible)Value).ToUInt32(provider); }
    public ulong    ToUInt64(IFormatProvider provider)   {return ((IConvertible)Value).ToUInt64(provider); }
}
Add-Type -Path "$PSScriptRoot\type.cs"

$c = [C]::new('value')
$c.ToString()
[string]$c

Expected behavior

value
value

Actual behavior

PowerShell 7

value
OperationStopped: C:\test.ps1:5
Line |
   5 |  [string]$c
     |  ~~~~~~~~~~
     | Unable to cast object of type 'C' to type 'System.String'.

PowerShell 5.1

value
value

Environment data

Name                           Value
----                           -----
PSVersion                      7.0.0-rc.2
PSEdition                      Core
GitCommitId                    7.0.0-rc.2
OS                             Microsoft Windows 6.3.9600
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0.}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-BugIssue has been identified as a bug in the productResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions