2014-10-22 18 views
12

Tôi đã thực hiện một lỗi đánh máy đáng tiếc nhất chi phí cho tôi một thời gian khá quý:Thuộc tính Count hoạt động như thế nào trong Powershell?

$errors.Count 

này trả về "0", ngay cả khi có những sai sót, bởi vì tên biến nên ít. này không công việc:

$error.clear()    # To ensure a correct repro 
Copy-Item asdf fdsa   # Will show an error 
$error.Count     # Will output "1" 

Tuy nhiên, bây giờ tôi muốn biết tại sao $errors.Count đã cho tôi bất cứ điều gì ở tất cả, và tại sao nó đã cho tôi "0". Vì vậy, tôi đã đi vào để làm một số xét nghiệm và có kết quả như sau:

$asdf.Count     # Will output "0" 
$nrOfEinsteinsInSpace.Count # Will output "0" 
$a = 0; $a.Count;    # Will output "1" 
$b = 2; $a.Count;    # Will output "1" 
$x = 1,2,3; $x.Count;   # Will output "3" 

Và thu thập dữ liệu thậm chí nhiều hơn để có thể đặt một câu hỏi hợp lý ở đây tôi đã làm:

$true.Count     # Will output "1" 
$false.Count     # Will output "1" 

Vì vậy, chúng ta có các trường hợp khác nhau:

  1. Biến dạng tương tự, trong đó .Count sẽ xuất số lượng mục.
  2. Biến không tồn tại, trong đó .Count sẽ xuất "0".
  3. Biến được khai báo, trong đó .Count sẽ xuất "1".
  4. Biến tích hợp, trong đó .Count sẽ xuất "1".

Trường hợp 2, 3 và 4 không có ý nghĩa gì với tôi (chưa). Chuyện gì đang xảy ra ở đây? Tài liệu này ở đâu? Tài sản .Count hoạt động như thế nào?

Trả lời

14

Bắt đầu từ PowerShell V3, thuộc tính Đếm và Độ dài nhận được điều trị rất đặc biệt không liên quan đến dữ liệu loại mở rộng (còn được gọi là ETS hoặc hệ thống kiểu mở rộng).

Nếu cá thể có thuộc tính Đếm/Độ dài, thì mọi thứ tiếp tục hoạt động như đã làm trong V1/V2 - giá trị từ cá thể được trả về.

Nếu trường hợp không có thuộc tính Đếm/Độ dài, bắt đầu bằng V3, thay vì đó là lỗi, bạn sẽ quay lại 1. Và nếu phiên bản là $ null, bạn sẽ quay lại 0. Nếu bạn đã bật chế độ nghiêm ngặt, bạn sẽ gặp lỗi như trong phiên bản V2.

Tôi thừa nhận điều này hơi lạ, nhưng nó giải quyết được vấn đề chung khi lệnh ghép ngắn trả về 0, 1 hoặc nhiều đối tượng.

Thông thường, bạn sẽ lặp qua các kết quả đó qua đường ống hoặc với tuyên bố foreach. Ví dụ:

dir nosuchfile* | % { $_ } 
foreach ($item in dir nosuchfile*) { $_ } 

Trong trường hợp trên, V2 thực sự sẽ nhập vòng nếu lệnh không trả về bất kỳ giá trị nào. Điều đó đã được thay đổi trong V3 để phù hợp hơn với mong đợi của mọi người, nhưng điều đó cũng có nghĩa là:

foreach ($item in $null) { $_ } 

cũng không bao giờ đi vào vòng lặp.

Câu lệnh for là một cách khác để lặp qua các kết quả, ví dụ:

$results = dir nosuchfile* 
for ($i = 0; $i -lt $results.Count; $i++) { $results[$i] } 

Trong ví dụ này, không quan trọng có bao nhiêu đối tượng trong kết quả $, vòng lặp hoạt động tốt. Lưu ý rằng trong V1/V2, bạn sẽ đã viết:

$results = @(dir nosuchfile*) 

Điều này đảm bảo $ kết quả là một mảng, nhưng cú pháp này là xấu xí và nhiều folks sẽ quên nó, vì thế mà thay đổi để hỗ trợ Đếm/Chiều dài trong một hơi cách tha thứ hơn.

+0

Wow, một câu trả lời khá khác so với hai câu trả lời khác của @DavidBrabant và Paul. Tôi đánh giá cao cả hai nỗ lực, tôi không chắc liệu tôi có đủ điều kiện để quyết định câu trả lời nào chấp nhận hay không. Sẽ phải kiểm tra tại nơi làm việc vào ngày mai nếu tôi thấy sự khác biệt tương tự giữa V2 và V3. Cảm ơn vì đã dành thời gian cho tôi! – Jeroen

+4

Tôi là nhà phát triển trong nhóm PowerShell đã triển khai thực hiện điều này, vì vậy hãy bỏ qua những kỷ niệm bị lỗi, câu trả lời của tôi là có thẩm quyền như bạn có thể nhận được. –

+1

Hãy coi chừng rằng ** chế độ ** nghiêm ngặt vẫn ném một lỗi như ghi chú Jason! Điều đó khiến tôi gãi đầu mình ... –

3

Sau đây là cách tôi nghĩ rằng nó hoạt động:

Trường hợp 1: Trong Mảng các .Count tài sản thực sự liên kết đến .Length tài sản đó cho thấy số lượng các mục trong Array

Trường hợp 2: biến không exitent được tạo tự động bởi powershell và được khởi tạo với giá trị $null

Trường hợp 3/4: Ngày này tôi không chắc chắn lý do tại sao nó xảy ra nhưng vì cả String lẫn Int hoặc boolean Objects đều có thuộc tính .Count tôi có thể tưởng tượng rằng Thuộc tính được thừa kế bởi một đối tượng cha mẹ.

Các hành vi gợi ý rằng các biến được coi là mảng như vậy với 1 Giá trị giao đầu ra sẽ là 1, mà không có một giá trị kết quả sẽ là 0.

Edit: Vì lợi ích của sự hoàn chỉnh ở đây là Link vào Tài liệu: Technet, nhờ @David Brabant

5

Để bổ sung cho câu trả lời của Paul, điều này có thể liên quan đến extended type data. Để trích dẫn phần có liên quan của tài liệu:

Dữ liệu loại mở rộng xác định thuộc tính và phương pháp bổ sung ("thành viên") của các loại đối tượng trong Windows PowerShell.Bạn có thể mở rộng bất kỳ loại nào được Windows PowerShell hỗ trợ và sử dụng các thuộc tính và phương thức được thêm vào giống như cách bạn sử dụng các thuộc tính được xác định trên các loại đối tượng.

Và:

Có ba nguồn dữ liệu kiểu mở rộng trong Windows PowerShell phiên. Các tệp Types.ps1xml trong thư mục cài đặt Windows PowerShell được tải tự động vào mọi phiên Windows PowerShell.

Nếu bạn mở tập tin đó Types.ps1xml (trong $pshome), bạn sẽ thấy điều này vào lúc bắt đầu của tập tin:

<Type> 
     <Name>System.Array</Name> 
     <Members> 
      <AliasProperty> 
       <Name>Count</Name> 
       <ReferencedMemberName>Length</ReferencedMemberName> 
      </AliasProperty> 
     </Members> 
    </Type> 

Vì vậy, tôi đoán là bằng cách cung cấp ".Count" bất động sản , PowerShell giả định đây là một mảng.

+0

ha i đã đúng :) cảm ơn vì liên kết đến tài liệu! – Paul

Các vấn đề liên quan