Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

My understanding of PowerShell's string embedding syntax "$($object)" has always been that $object is cast to [System.String], which invokes $object.ToString(). However, I've noticed this curious behavior with the [DateTime] class using PowerShell 4.0 on Windows 8.1.

PS> $x = Get-Date

PS> $x.GetType() | select -ExpandProperty Name
DateTime

PS> $x.ToString()
2015-05-29 13:36:06

PS> [String]$x
05/29/2015 13:36:06

PS> "$($x)"
05/29/2015 13:36:06

It seems that "$($object)" gives the same behavior as casting to string, but is clearly producing a different result from $object.ToString(). $x.ToString() is consistent with the short date format set in intl.cpl (yyyy-MM-dd). [String]$x appears to use the en-US default.

It is possible this is simply a bug in the DateTime class, but I'm more surprised that the different methods of converting an object to a string produce different results. What are the rules for casting an object to a string, if not calling ToString()? Is the DateTime class simply a special case because of its overloading of ToString(String)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
394 views
Welcome To Ask or Share your Answers For Others

1 Answer

If an object implements the IFormattable interface, then PowerShell will call IFormattable.ToString instead of Object.ToString for the cast operation. A similar thing happens for static Parse method: if there is an overload with IFormatProvider parameter, then it would be called.

Add-Type -TypeDefinition @'
    using System;
    using System.Globalization;
    public class MyClass:IFormattable {
        public static MyClass Parse(string str) {
            return new MyClass{String=str};
        }
        public static MyClass Parse(string str,IFormatProvider fp) {
            return new MyClass{String=str,FormatProvider=((CultureInfo)fp).DisplayName};
        }
        public string String {get;private set;}
        public string FormatProvider {get;private set;}
        public override string ToString() {
            return "Object.ToString()";
        }
        string IFormattable.ToString(string format,IFormatProvider fp) {
            return string.Format("IFormattable.ToString({0},{1})",format,((CultureInfo)fp).DisplayName);
        }
    }
'@
[String](New-Object MyClass) #Call IFormattable.ToString(null,CultureInfo.InvariantCulture)
[MyClass]'Test'              #Call MyClass.Parse("Test",CultureInfo.InvariantCulture)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...