Get-Date приведение к строке против ToString()
Мое понимание синтаксиса встраивания строк в PowerShell "$($object)"
всегда было так $object
брошен в [System.String]
, который вызывает $object.ToString()
, Тем не менее, я заметил это любопытное поведение с [DateTime]
класс с использованием PowerShell 4.0 на 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
Кажется, что "$($object)"
дает то же поведение, что и приведение к строке, но явно дает другой результат от $object.ToString()
, $x.ToString()
соответствует формату короткой даты, установленному в intl.cpl (гггг-мм-дд). [String]$x
По-видимому, используется по умолчанию в США.
Возможно, это просто ошибка в классе DateTime, но меня больше удивляет, что разные методы преобразования объекта в строку дают разные результаты. Каковы правила приведения объекта в строку, если не вызывается ToString()
? Является ли класс DateTime просто частным случаем из-за его перегрузки ToString(String)
?
2 ответа
Если объект реализует 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)
Ваш вопрос - не вопрос PowerShell, а вопрос.NET. Скрипты PowerShell могут использовать структуру.NET [datetime] как есть, то есть PowerShell не меняет своего поведения.
Каковы правила приведения объекта к строке, если не вызывается ToString()?
Кастинг использует определения, инвариантные к культуре. 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
Обратите внимание, что приведенный выше код будет производить различную печать, если он выполняется в версиях PowerShell не для ISE.