• Aucun résultat trouvé

T YPE LITERALS

Dans le document Bruce PayetteSECOND EDITION (Page 127-132)

Working with types

3.5 T YPE LITERALS

In earlier sections, you saw a number of things that looked like [type]. These are the type literals. In PowerShell, you use type literals a variety of ways. You use them to specify a particular type. They can be used as operators in a cast (an operation that converts an object from one type to another), as part of a type-constrained variable declaration (see chapter 4), or as an object itself. Here’s an example of a cast using a type literal:

$i = [int] "123"

In this example, you’re casting or converting a string into a number, specifically an instance of primitive .NET type System.Int32. You could use the longer .NET type name to accomplish the same thing:

$i = [System.Int32] "123"

Now let’s look at something a bit more sophisticated. If you wanted to make this into an array of integers, you’d do this:

$i = [int[]][object[]] "123"

In this example, you’re not just casting the basic type, you’re also changing it from a scalar object to an array. Notice that you had to do this in two steps. In the first step, you converted it into a collection but without changing the element type. In the sec-ond step, you converted the types of the individual elements. This follows the general type converter rule that no more than one conversion will be performed in a single step. This rule makes it much easier to predict what any given conversion will do.

NOTE In this case, converting a scalar value into an array is so com-mon that we added support for doing this directly in PowerShell v2.

You can simply say $i = [int[]] "123". 3.5.1 Type name aliases

Obviously, the shorter type name (or type alias, as it’s known) is more convenient.

Table 3.4 lists all the type aliases defined in PowerShell and the .NET types they cor-respond to. It also indicates which version of PowerShell the alias is available in.

(Another change that was made in v2 is that there are no longer separate aliases for arrays of the base type. As a result, these aren’t shown in the table as they were in the first version of the book.) Anything in the System.Management.Automation namespace is specific to PowerShell. The other types are core .NET types and are cov-ered in the MSDN documentation.

TYPELITERALS 97 Type resolution

When PowerShell resolves a type name, it first checks the type name alias table;

then it checks to see whether a type exists whose full name matches the string specified. Finally it prepends the type with system. and checks to see whether a type exists that matches the new string. This means things that are in the System namespace look like they might be aliased.

For example, the type System.IntPtr can be referred to as [intpr] even though it’s not in the alias table. For the most part, this referral is transparent. The one time it does matter is if, for some reason, a type was added to the system that lives in the top-level namespace. In this case, [intptr] would refer to the new type and you’d have to use [system.intptr] to refer to the system type. This should never happen because types should always be in namespaces.

Table 3.4 PowerShell type aliases and their corresponding .NET types

Type alias Corresponding .NET type Version

[int] System.Int32 1, 2

[long] System.Int64 1, 2

[string] System.String 1, 2

[char] System.Char 1, 2

[bool] System.Boolean 1, 2

[byte] System.Byte 1, 2

[double] System.Double 1, 2

[decimal] System.Decimal 1, 2

[float] System.Single 1, 2

[single] System.Single 1, 2

[regex] System.Text.RegularExpressions.Regex 1, 2

[array] System.Array 1, 2

[xml] System.Xml.XmlDocument 1, 2

[scriptblock] System.Management.Automation.ScriptBlock 1, 2 [switch] System.Management.Automation.SwitchParameter 1, 2

[hashtable] System.Collections.Hashtable 1, 2

[ref] System.Management.Automation.PSReference 1, 2

[type] System.Type 1, 2

[psobject] System.Management.Automation.PSObject 1, 2 [pscustomobject] System.Management.Automation.PSObject 2 [psmoduleinfo] System.Management.Automation.PSModuleInfo 2

3.5.2 Generic type literals

There’s a special kind of type in .NET called a generic type, which let you say some-thing like “a list of strings” instead of just “a list.” And although you could do this without generics, you’d have to create a specific type for the type of list. With gener-ics, you create one generic list type (hence the name) and then parameterize it with the type it can contain.

NOTE Generic type literal support was added in v2. In v1, it was pos-sible to express a type literal, but it was a painful process. You’ll learn how to do this later in the book.

This example shows the type literal for a generic list (System.Collections .Generic.List) of integers:

PS (1) > [system.collections.generic.list[int]] | ft -auto IsPublic IsSerial Name BaseType

---- ---True ---True List`1 System.Object

If you look at the type literal, it’s easy to see how the collection element type is expressed: [int]. This is essentially a nested type literal where the type parameter is enclosed in nested square brackets. Create an instance of this type:

PS (2) > $l = new-object system.collections.generic.list[int]

Then add some elements to it:

PS (3) > $l.add(1) PS (4) > $l.add(2)

Get the count of elements added and list the elements:

PS (5) > $l.count 2

[powershell] System.Management.Automation.PowerShell 2 [runspacefactory] System.Management.Runspaces.RunspaceFactory 2 [runspace] System.Management.Automation.Runspaces.Runspace 2

[ipaddress] System.Net.IPAddress 2

[wmi] System.Management.ManagementObject 1, 2

[wmisearcher] System.Management.ManagementClass 1, 2

[wmiclass] System.Management.ManagementClass 1, 2

[adsi] System.DirectoryServices.DirectoryEntry 1, 2

[adsisearcher] System.DirectoryServices.DirectorySearcher 1, 2 Table 3.4 PowerShell type aliases and their corresponding .NET types (continued)

Type alias Corresponding .NET type Version

TYPELITERALS 99

PS (6) > $l 1

2

Try to add something that isn’t an integer:

PS (7) > $l.add("hello")

Cannot convert argument "0", with value: "hello", for "Add" to type "System.Int32": "Cannot convert value "hello" to type "System .Int32". Error: "Input string was not in a correct format.""

at line:1 char:7 $l.add <<<< ("hello")

+ CategoryInfo : NotSpecified: (:) [], MethodExcep tion

+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCa stArgument

This results in a type error because "hello" can’t be converted into an integer. Now, if the string could be converted to a number, as in this example

PS (8) > $l.add("123") PS (9) > $l.count 3

PowerShell would take care of the conversion and the operation could proceed with-out error.

Finally, let’s look at a type that requires more than one type parameter. For exam-ple, a generic dictionary requires two type parameters: the type of the keys and the type of the values. Here’s what this looks like:

PS (10) > [system.collections.generic.dictionary[string,int]] |

>> Format-List -auto

IsPublic IsSerial Name BaseType ---- ---True ---True Dictionary`2 System.Object

The two type parameters are separated by a comma inside the square brackets.

Now let’s take a trip into the “too-much-information” zone and look in detail at the process PowerShell uses to perform all of these type conversions. On first reading, you’ll probably want to skim this section but read it in detail later when you’re more comfortable with PowerShell. This is a “spinach” section—you may not like it, but it’s good for you.

The primary uses for type literals are in performing type conversions and invoking static methods. We’ll look at both of these uses in the next two sections.

3.5.3 Accessing static members with type literals

As mentioned, a common use for type literals is for accessing static methods on .NET classes. You can use the Get-Member cmdlet to look at the members on an object. To view the static members, use the -Static flag:

PS (1) > [string] | get-member -static TypeName: System.String

Name MemberType Definition ----

---Compare Method static System.Int32 ---Compare(String...

CompareOrdinal Method static System.Int32 CompareOrdinal...

Concat Method static System.String Concat(Object...

Copy Method static System.String Copy(String str) Equals Method static System.Boolean Equals(Strin...

Format Method static System.String Format(String...

Intern Method static System.String Intern(String...

IsInterned Method static System.String IsInterned(St...

IsNullOrEmpty Method static System.Boolean IsNullOrEmpt...

Join Method static System.String Join(String s...

op_Equality Method static System.Boolean op_Equality(...

op_Inequality Method static System.Boolean op_Inequalit...

ReferenceEquals Method static System.Boolean ReferenceEqu...

Empty Property static System.String Empty {get;set;}

This code will dump out all the static members on the .NETSystem.String class. If you want to call one of these methods, you need to use the :: operator. Let’s use the join method to join an array of string. First create the array:

PS (2) > $s = "one","two","three"

Then use the join method to join all the pieces into a single string with plus signs in between:

PS (3) > [string]::Join(' + ', $s) one + two + three

PS (4) >

Example: using advanced math functions

A good example of the power of static methods is the [math]class from the .NET Framework. This class—[System.Math]—is a pure static class. This means you can’t create an instance of it—you can only use the static methods it provides. Again, let’s use the Get-Member cmdlet to look at the methods. Here’s a truncated listing of the output you’d see:

PS (1) > [math] | get-member -static TypeName: System.Math

Name MemberType Definition ----

---Abs Method static System.Single ---Abs(Single va...

Acos Method static System.Double Acos(Double d) Asin Method static System.Double Asin(Double d) Atan Method static System.Double Atan(Double d) Atan2 Method static System.Double Atan2(Double ...

: :

TYPECONVERSIONS 101

Sqrt Method static System.Double Sqrt(Double d) Tan Method static System.Double Tan(Double a) Tanh Method static System.Double Tanh(Double v...

Truncate Method static System.Decimal Truncate(Dec...

E Property static System.Double E {get;}

PI Property static System.Double PI {get;}

As you can see, it contains a lot of useful methods and properties. For example, it contains useful constants like Pi and e as static properties:

PS (2) > [math]::Pi 3.14159265358979 PS (3) > [math]::e 2.71828182845905 PS (4) >

There are also all the trigonometric functions:

PS (4) > [math]::sin(22) -0.00885130929040388 PS (5) > [math]::cos(22) -0.999960826394637 PS (6) >

As we’ve said, types in PowerShell provide tremendous power and breadth of capabil-ities. In many cases, before rolling your own solution it’s worth browsing the MSDN documentation on the .NET libraries to see if there’s something you can use to solve your problems. Now that you’ve seen the types, let’s look at how PowerShell does type conversions.

Dans le document Bruce PayetteSECOND EDITION (Page 127-132)