我对PowerShell的字符串嵌入语法"$($object)"
的理解始终是$object
强制转换为[System.String]
,后者调用$object.ToString()
。但是,我在Windows 8.1上使用PowerShell 4.0的[DateTime]
类注意到了这种奇怪的行为。
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
似乎"$($object)"
给出了与转换为字符串相同的行为,但显然会产生与$object.ToString()
不同的结果。 $x.ToString()
与intl.cpl(yyyy-MM-dd)中设置的短日期格式一致。 [String]$x
似乎使用了en-US默认值。
这可能只是DateTime类中的一个错误,但我更惊讶的是,将对象转换为字符串的不同方法会产生不同的结果。如果不调用ToString()
,将对象强制转换为字符串的规则是什么? DateTime类只是一个特例,因为它超载ToString(String)
?
答案 0 :(得分:8)
如果对象实现了IFormattable
接口,那么PowerShell将为转换操作调用IFormattable.ToString
而不是Object.ToString
。类似的事情发生在静态Parse
方法中:如果有IFormatProvider
参数的重载,则会调用它。
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)
答案 1 :(得分:4)
您的问题不是PowerShell问题,而是.NET问题。 PowerShell脚本可以原样使用.NET结构[datetime],即PowerShell不会改变其行为。
如果不调用ToString(),将对象强制转换为字符串的规则是什么?
Casting使用文化不变定义。 ToString()
方法可以包含与文化相关的实现,因为它是可覆盖的。
DateTime类是否只是一个特例,因为它超载了ToString(String)?
首先,DateTime不是一个类;这是一个结构。
其次,没有ToString()
方法重载; 在这种情况下,正确的面额覆盖(它覆盖了Object.ToString()
方法)。
为了更好地理解我的意思,请在不同的文化中打印这些非常有趣的日期和时间(复制,粘贴和运行):
function f{
$x=get-date
[CultureInfo]$currentCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('en-US')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('ar-IQ')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('de-DE')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('ru-RU')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('fr-FR')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('zh-CN')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('zh-HK')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('zh-TW')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('hu-HU')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('ko-KR')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('ja-JP')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('ka-GE')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=[CultureInfo]::CreateSpecificCulture('pt-BR')
$x.ToString()
[System.Threading.Thread]::CurrentThread.CurrentCulture=$currentCulture
}
f
请注意,如果在ISE或非ISE版本的PowerShell中运行,上面的代码将产生不同的打印。