2012-04-13 36 views
8

Tôi có một trường có kiểu 'đối tượng'. Khi tôi kiểm tra nó trong cửa sổ Watch của studio trực quan, tôi thấy Object của nó [] và khi tôi đi sâu vào các phần tử tôi thấy mỗi phần tử là một chuỗi.Tại sao tôi không thể chuyển đổi một đối tượng (mà thực sự là đối tượng []) thành chuỗi []?

Nhưng khi tôi cố gắng đúc này cho một String [] Tôi nhận được lỗi này:

Cannot cast 'MyObject' (which has an actual type of 'object[]') to 'string[]' string[]

Bất kỳ lý do tại sao tôi không thể làm diễn viên này? Cách tốt nhất để chuyển đổi đối tượng này thành mảng chuỗi là gì?

+0

Bạn đang truyền mảng của mình như thế nào? Nói chung? Bạn cần phải đúc từng phần tử trong mảng của mình. – Msonic

+0

Vâng, anh ấy rõ ràng đang đúc nó như một tổng thể. –

+1

Phương sai mảng tham chiếu là một cách khác; bạn có thể cast cái gì đó ** thực sự là một 'string []' như một 'object []', nhưng để đi theo một cách khác, nó thực sự phải là một 'string []' –

Trả lời

16
string[] newarr = Array.ConvertAll(objects, s => (string)s); 

--EDIT--

kể từ khi bạn đã nói Tôi có một object (biết rằng nó là một object[] thực sự)

string[] newarr = Array.ConvertAll((object[])objects, s => (string)s); 
+0

điều này dường như không biên dịch. . tôi nhận được lỗi: Không thể suy luận loại suy luận. . . – leora

+0

@leora xem câu trả lời được cập nhật. –

-1

Bạn có thể chuyển đổi các thựcstring[] đến object[].

Đây là một Array covariance

thể tìm thấy một ví dụ rõ ràng trong liên kết.

+0

@ downvoter: quan tâm giải thích? – Tigran

+0

không phải của tôi d/v nhưng có lẽ b/c bạn không bao gồm ví dụ –

0
object[] original = new object[]{"1", "2"}; 
//some code in between here 
object obj = original ; 
object[] objArray = (object[])obj; 
string[] newArray = new string[objArray.Length]; 
for(int i = 0; i < newArray; i++) 
{ 
    newArray[i] = (string)objArray[i]; 
} 

Các câu trả lời khác ở đây cho bạn thấy cách thực hiện chuyển đổi nhanh hơn/ngắn hơn. Tôi đã viết toàn bộ điều như thế này bởi vì nó cho thấy những gì đang thực sự xảy ra và những gì cần phải xảy ra. Bạn nên sử dụng một trong những phương pháp đơn giản hơn trong mã sản xuất thực tế của mình.

+0

hmm. . vì một số lý do giải pháp của bạn là giải pháp duy nhất biên dịch và làm việc cho tôi. . – leora

+0

@leora Hầu hết mọi người khác đã giải quyết một phần vấn đề, nhưng không phải toàn bộ vấn đề. Họ giải quyết phần đó một cách rõ ràng hơn/thanh lịch hơn. Như tôi đã nói, mã này được thiết kế để hiển thị cho bạn những gì cần phải xảy ra, ngay cả khi có phương pháp thư viện thực hiện một nửa số đó cho bạn. – Servy

+0

@Servy 'nhưng không phải là toàn bộ điều' bạn có chắc chắn không ?. –

-1

Bạn nên bỏ từng phần tử trong bộ sưu tập chứ không phải chính bộ sưu tập.

object[] ovalues = new object[] { "alpha", "beta" }; 
string[] svalues = ovalues.Cast<string>().ToArray(); 
+0

tôi không có đối tượng []. .i chỉ có đối tượng. . cho rằng tôi nhận được "Không thể phân giải được Cast" – leora

+0

@leora 'bằng System.Linq;' –

+0

hmm. . . tôi đã có tham chiếu đó rồi. . . – leora

23

Đây là một tính năng đặc biệt khó hiểu của C#. Đây là thỏa thuận.

Trong suốt cuộc thảo luận này, chúng tôi giả định rằng loại phần tử của một mảng là một loại tham chiếu, không phải là một loại giá trị.

C# hỗ trợ hiệp phương sai mảng không an toàn. Điều đó có nghĩa rằng nếu bạn có một mảng của chuỗi, bạn có thể chuyển nó sang một loạt các đối tượng, bởi vì một chuỗi có thể được chuyển đổi sang một đối tượng:

string[] a1 = { "hello", "goodbye" }; 
object[] a2 = a1; // Legal 

Nếu bạn sau đó cố gắng để có được một yếu tố ra khỏi a2, nó hoạt động:

object o3 = a2[0]; 

đó là quy phạm pháp luật vì a2[0] thực sự là a1[0], mà là một chuỗi, đó là mui trần để phản đối.

Tuy nhiên, nếu bạn cố gắng để ghi đến mảng sau đó bạn sẽ nhận được một lỗi khi chạy:

a2[0] = new object(); 

này thất bại khi chạy vì a2thực sự một mảng các chuỗi, và bạn không thể đặt một chuỗi không vào một chuỗi các chuỗi.

Vì vậy, C# đã bị phá vỡ khủng khiếp; có thể viết một chương trình biên dịch và trông bình thường nhưng đột nhiên đổ vỡ với một kiểu ngoại lệ trong thời gian chạy vì bạn đã cố gắng đặt một đối tượng vào một mảng các đối tượng không thực sự là một mảng các đối tượng.

Tính năng bạn muốn là thậm chí bị vỡ nhiều hơn số và cảm ơn sự tốt lành C# không hỗ trợ tính năng này. Các tính năng mà bạn muốn là:

object[] a4 = { "Hello" }; 
string[] a5 = a4; 

Đó sẽ là mảng không an toàn contravariance. Nó phá vỡ khủng khiếp như thế này:

a4[0] = new Customer(); // Perfectly legal 
string s6 = a5[0]; 

Và bây giờ chúng ta chỉ cần sao chép một khách hàng vào một biến kiểu chuỗi.

Bạn nên tránh bất kỳ loại hiệp phương sai hoặc đối nghịch nào; mâu thuẫn mảng là, như bạn đã phát hiện, không hợp pháp, và hiệp phương sai mảng là làm cho ít thời gian bom trong chương trình của bạn mà đi bất ngờ. Làm cho mảng của bạn đúng loại để bắt đầu.

+1

Tôi đồng ý với hầu hết những gì bạn nói, nhưng tôi không đồng ý rằng mâu thuẫn mảng là _even more_ bị phá vỡ so với hiệp phương sai mảng - chúng dường như hoàn toàn tình huống kép. Với contravariance mảng, bạn có thể đọc và ghi vào mảng đối tượng, ghi vào mảng chuỗi và đọc từ mảng chuỗi miễn là đối tượng của một kiểu khác không được ghi vào vị trí đó thông qua mảng đối tượng. Với hiệp phương sai, bạn có thể đọc và ghi vào mảng chuỗi, đọc từ mảng đối tượng và ghi vào mảng đối tượng miễn là bạn đang chèn một chuỗi vào vị trí đó. – kvb

+4

@kvb: Tôi lấy ý kiến ​​của bạn. Tôi nói rằng nó "thậm chí còn bị phá vỡ" bởi vì trong trường hợp covariant, kịch bản bị hỏng là: chuyển đổi-theo-by-ghi thất bại. Nhưng vì nhiều người sử dụng mảng như * các mảng chỉ đọc * hiệu quả - chúng chỉ viết khi mảng được tạo ra - không có chuyển đổi theo sau bởi ghi, chỉ có chuyển đổi theo sau là đọc. Tức là, nó có thể * chỉ * phá vỡ nếu có * ghi * theo chuyển đổi. Nhưng trường hợp contravariant có thể phá vỡ * bất kỳ * đọc sau khi chuyển đổi; mảng có thể không phải là tất cả các chuỗi để bắt đầu! –

0

Các quy tắc trong lập trình hướng đối tượng là -

"class Derived luôn có thể được loại đúc tới lớp cơ sở" VÀ "Một lớp cơ sở có thể được đúc để lớp có nguồn gốc chỉ khi dụ hiện tại mà lớp cơ sở giữ tắt là lớp thực sự có nguồn gốc "

ví dụ (A là cơ sở và B có nguồn gốc)

A a = new B(); // legal; 
B b = (B) a ; // legal as "a" is actually B (in first statement) 

bất hợp pháp:>

A a = new A(); 
B b = (B) a; // not legal as "a" is A only. 

Cùng một điều được áp dụng cho đối tượng và các lớp String. Object là lớp cơ sở và chuỗi là Derived class.

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