2011-09-01 38 views
11

Các mã sau hoạt động:Đúc Danh sách <x> vào danh sách <y>

List<JsonStock> stock = new List<JsonStock>(); 

foreach(tblStock item in repository.Single(id).tblStocks)     
    stock.Add((JsonStock) item); 

Vì vậy, tự nhiên bạn sẽ nghĩ rằng mã này sẽ làm việc quá:

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<JsonStock>().ToList() 

Nhưng tôi nhận được lỗi Invalid cast operation - không ai biết tại sao điều đó có thể xảy ra?

CẬP NHẬT

tblStocks là danh sách các đối tượng LINQ to SQL, tblStock.
JsonStock là phiên bản đơn giản của lớp tblStock và được trả về trang web dưới dạng đối tượng JSON.

Nhà điều hành sau đây được xây dựng để làm đúc:

public partial class tblStock{ 
    public static explicit operator JsonStock(tblStock stock){ 
     JsonStock item = new JsonStock 
     { 
      boxes = stock.boxes, 
      boxtype = stock.tblBoxType.name, 
      boxtype_id = stock.boxtype_id, 
      grade = stock.grade, 
      packrate = stock.packrate, 
      weight = stock.weight 
     }; 

     return item; 
    } 
} 
+3

loại 'tblStocks' được xác định như thế nào? –

+0

Chỉ là một ý tưởng, không chắc chắn về điều này: 'repository.Single (id) .tblStocks' trả về một mảng hoặc danh sách' JsonStock', vì vậy khi bạn cố gắng truyền như 'JsonStock' nó than phiền ... – Marco

+0

@Marco - no nó không nên phàn nàn. –

Trả lời

6

Cast được sử dụng để thay đổi một bộ sưu tập không chung vào một chung chung, ví dụ: nó thực hiện một hoạt động unboxing. Nó không thể được sử dụng theo cách bạn muốn.
Khi bạn có một cái nhìn tại các triển khai CastCastIterator nó sử dụng, bạn sẽ thấy, mà phải mất một đối tượng và phôi nó vào loại quy định:

foreach (object current in source) 
{ 
    yield return (TResult)current; 
} 

chỉ này hoạt động nếu current thực sự là một TResult . Không có chuyển đổi tùy chỉnh nào được áp dụng trong trường hợp này.
Đây là hành vi mặc định, bạn có thể kiểm tra nó tự hỏi:

double d = 0.0; 
object tmp = d; 
int i = (int)tmp; // throws the same exception you are getting 

gì bạn muốn đạt được tốt nhất với một đơn giản Select nếu tblStocks là đếm được generic:

List<JsonStock> stock = repository.Single(id).tblStocks 
            .Select(x => (JsonStock)x).ToList(); 

Hoặc, nếu tblStocks là một số không chung chung, bạn cần phải kết hợp CastSelect:

List<JsonStock> stock = repository.Single(id).tblStocks.Cast<tblStock>() 
            .Select(x => (JsonStock)x).ToList(); 

Điều này trước tiên sẽ bỏ hộp các đối tượng trong tblStocks thành loại thực của chúng (tblStock) và sau đó truyền đến loại bạn muốn (JsonStocks).

+2

+1 để hoàn thành nhất – UrbanEsc

1

Thay vì sử dụng Cast, xem xét sử dụng OfType. Trong Cast, nếu mục bạn đang xử lý không phải là loại mong muốn, bạn sẽ nhận được InvalidCastException. Với OfType, nó sẽ bẫy cho việc truyền không hợp lệ và chỉ trả lại các mục thực sự là kiểu mà bạn đang tìm kiếm.

List<JsonStock> stock = repository.Single(id).tblStocks.OfType<JsonStock>().ToList() 

Nếu bạn quay trở lại danh sách sản phẩm nào tuy nhiên, tôi nghi ngờ rằng tblStocks của bạn thực sự không trả JsonStocks và bạn đang cố gắng để dự án một số loại khác (tblStock?) Vào một DTO (JsonStock). Nếu sau này là trường hợp, bạn cần phải sử dụng Chọn để chiếu vào loại mới từ loại cơ bản.

List<JsonStock> stock = repository.Single(id).tblStocks 
         .Select(stock => new JsonStock 
          { 
           Id = stock.Id, 
           Val1 = stock.Val1, 
           Val2 = stock.Val2, 
           ... 
          } 
         .ToList(); 
1
  • tblStocks.Cast<JsonStock>() thực hiện truyền.
  • (JsonStock) item thực hiện một dàn diễn viên hoặc áp dụng chuyển đổi được xác định tùy chỉnh.

Vì tblStock là một lớp LINQ to SQL và JsonStock là một lớp tùy chỉnh do bạn tạo ra, không có lớp con nào khác được tạo bởi bạn. Vì vậy, bạn không thể đúc giữa hai người.

Để khắc phục điều này, bạn có thể sử dụng Select khoản của LINQ và tự chuyển đổi các yếu tố:

List<JsonStock> stock = repository.Single(id).tblStocks 
    .Select(item => (JsonStock) item).ToList(); 
2

nhà khai thác chuyển đổi ngầm và rõ ràng là ignored by Cast. Trong trường hợp của bạn có nghĩa là

public static explicit operator JsonStock(tblStock stock) 

được bỏ qua bởi Cast họ tuy nhiên không được bỏ qua trong trường hợp foreach

+0

Nói ai? Nếu điều đó là đúng 'Enumerable.Cast ()' sẽ không có ý nghĩa gì cả. http://msdn.microsoft.com/en-us/library/bb341406.aspx không chứa thông tin để hỗ trợ khiếu nại của bạn. – VVS

+0

@VVS: Bạn không hiểu mục đích của 'Enumerable.Cast ()'. Đầu vào là một số không chung chung. Kết quả là một số đếm chung. Toàn bộ mục đích của phương thức mở rộng này là tạo ra một kiểu gõ mạnh có thể đếm được từ một số không chung, bạn biết kiểu của các đối tượng từ đó. Xem câu trả lời của tôi để biết thêm chi tiết. –

+0

@VVS Nếu đọc kỹ, liên kết đó thực sự chứa thông tin để hỗ trợ khiếu nại của tôi cũng như liên kết trong câu trả lời của tôi. Liên kết bạn đã cung cấp các cuộc đàm phán về các toán tử _cast_ ở trên là toán tử _conversion_. Cú pháp cho việc sử dụng cả hai đều giống nhau (SomeType) nhưng điều đó không làm cho chúng giống nhau. Vì vậy, tôi thực sự không nhận được downvote của bạn –

1

Ahhh, những kỳ quan của quá tải nhà điều hành rõ ràng.

Vì vậy, để khắc phục sự cố, bạn có thể muốn gọi Chọn trước.

List<JsonStock> stock = repository.Single(id).tblStocks.Select(x => (JsonStock)x).ToList() 

Tuy nhiên tôi muốn nói rằng tình trạng quá tải của nhà cung cấp này là điều bạn nên loại bỏ. Xem xét thay thế nó bằng một hàm tạo bản sao như triển khai

class JsonStock 
{ 
    public JsonStock(tblStock other) 
    { 
      // copy values here 
    } 
} 
+0

+1 Cảm ơn giải pháp: P – Jimbo

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