2013-09-23 21 views
12

Tôi có chuyển đổi rõ ràng được xác định từ loại Bar để nhập Foo.IEnumerable <T> .Cast sẽ không hoạt động ngay cả khi một toán tử cast rõ ràng được xác định?

public class Bar 
{ 
    public static explicit operator Foo(Bar bar) 
    { 
    return new Foo(bar.Gar); 
    } 
} 

public class Foo 
{ 
    public string Gar { get; set; } 

    public Foo() { } 

    public Foo(string gar) { Gar = gar; } 
} 

Tuy nhiên, khi tôi làm:

using System.Linq; 

... 

var manyFoos = manyBars.Cast<Foo>(); 

Nó ném một ngoại lệ nói rằng nó không thể cast.

Làm cách nào để yêu cầu số Cast sử dụng toán tử truyền của tôi để thử chuyển đổi?

+1

Bạn có 'Bar'->' Foo' chuyển đổi được xác định, nhưng cố gắng làm điều ngược lại. – MarcinJuraszek

+0

Cảm ơn. Xin lỗi, ý tôi là ngược lại. Tôi chỉ cần gõ mã trực tiếp vào trang web mà không cần suy nghĩ quá nhiều. Tôi đã chỉnh sửa. –

+2

Vẫn không chính xác. 'bar.Gar'? Trường hợp nào này đến từ đâu? thanh không có tài sản 'Gar' –

Trả lời

2

Sử dụng Select:

var manyFoos = manyBars.Select(bar => (Foo)bar); 
+0

Tôi biết tôi có thể làm điều đó. Cảm ơn. Tôi không hỏi làm thế nào để dự án. Tôi hỏi - làm cách nào để Cast sử dụng toán tử truyền của tôi? Hoặc làm cách nào để tạo một kiểu dựng sẵn khác sử dụng tính năng truyền của tôi mà không cần phải dự án/chọn/chuyển đổi theo cách thủ công? –

1

Mã của bạn không thực sự biên dịch. Tôi cho rằng có một tài sản "Gar" trong lớp "Bar"?

public class Bar 
    { 
     public string Gar { get; set; } 

     public static explicit operator Foo(Bar bar) 
     { 
      return new Foo(bar.Gar); 
     } 
    } 

    public class Foo 
    { 
     public string Gar { get; set; } 

     public Foo() { } 

     public Foo(string gar) { Gar = gar; } 
    } 

static void Main(string[] args) 
     { 

      List<Bar> bars = new List<Bar>(); 
      for (int i = 0; i < 10; i++) 
       bars.Add(new Bar() { Gar = i.ToString() }); 

      var result = bars.Cast<Foo>(); 
     } 

+

tôi encaurage bạn đọc về hiệp phương sai.

Giả sử A có thể chuyển đổi thành B, X là covariant nếu X<A> có thể chuyển đổi thành X<B>.

Với khái niệm hiệp phương sai (và contravariance) của C#, "chuyển đổi" có nghĩa là chuyển đổi qua chuyển đổi tham chiếu ngầm định - chẳng hạn như A phân lớp B hoặc A thực hiện B. Chuyển đổi số, chuyển đổi quyền và chuyển đổi tùy chỉnh không được bao gồm.

Bạn phải làm điều đó với giao diện.

4

Phương thức linq Cast về cơ bản có hộp và hộp. Nó không nhận thức được các toán tử ngầm định hoặc ngầm định được định nghĩa trong C#, trình biên dịch xử lý các lời gọi phương thức chuẩn.

Bạn sẽ phải làm một cái gì đó như thế này:

var manyFoos = manyBars.Select(bar => (Foo)bar); 
+0

Cảm ơn bạn. Tôi chỉ hy vọng có một số phương pháp hoặc phần mở rộng tích hợp như 'Cast' hoặc' OfType' sử dụng dàn diễn viên của tôi bởi vì nhiều lần tôi đã gặp phải tình huống này. Tôi sẽ sử dụng một biến đổi cho bây giờ anyway. –

+0

@ WaterCoolerv2 Bạn có thể viết phương pháp mở rộng của riêng mình, có lẽ là phương pháp sử dụng sự phản chiếu. Nhưng đó sẽ không phải là thanh lịch cũng không hiệu quả như những gì bạn đang tìm kiếm. Tôi muốn gắn bó với phương pháp này trừ khi bạn * thực sự * để làm đúc động. –

+0

Cảm ơn, @ p.s.w.g. Tốt đẹp. –

8

khai thác Cast là phương pháp tĩnh rằng biên dịch cuộc gọi khi bạn sử dụng phôi trong mã. Chúng không thể được sử dụng động. Enumerable.Cast thực hiện một phép tính thời gian chạy của hai loại generic không bị ràng buộc, do đó, nó không thể biết trong thời gian biên dịch mà các toán tử sử dụng. Để làm những gì bạn muốn, bạn có thể sử dụng Select:

manyFoos.Select(foo => (Bar)foo); 
+0

Cảm ơn bạn. Tôi biết cách đi xung quanh nó bằng cách sử dụng một phép chiếu. Tôi đã chỉ nghĩ rằng nó sẽ được tốt đẹp cho 'Cast' hoặc' OfType', mặc dù tôi không lọc ở đây và 'OfType' sẽ không thích hợp, nên sử dụng dàn diễn viên tùy chỉnh của chúng tôi. Cảm ơn vì câu trả lời. –

4

Như tất cả các câu trả lời khác loại nhọn không được biết đến trong thời gian biên dịch từ Cast phương pháp không phải là generic. Nó chứa loại object và tạo dàn diễn viên rõ ràng cho T. điều này không thành công vì bạn không có toán tử chuyển đổi từ object đến Foo. Và điều đó cũng không thể.

Đây là công việc xung quanh việc sử dụng các động lực trong đó việc truyền sẽ được thực hiện trong thời gian chạy.

public static class DynamicEnumerable 
{ 
    public static IEnumerable<T> DynamicCast<T>(this IEnumerable source) 
    { 
     foreach (dynamic current in source) 
     { 
      yield return (T)(current); 
     } 
    } 
} 

Sau đó, sử dụng nó như

var result = bars.DynamicCast<Foo>();//this works 
+0

Cảm ơn. Tôi có thể viết phần mở rộng của riêng mình. Tôi chỉ hy vọng rằng có một cách cho 'Cast', phần mở rộng trong xây dựng để sử dụng toán tử của tôi. –

+0

@ WaterCoolerv2 Chào mừng bạn. Nhưng tiếc là AFAIK không có phương pháp được xây dựng trong: ( –

+0

Cảm ơn bạn. :-) Tôi vẫn không nói rằng nên có. Tôi chỉ nói - mục đích của việc tôi đặt câu hỏi này là - Tôi đã làm điều này trong nhiều năm và nhiều năm và đây là một trong những thú cưng của tôi và tôi không bao giờ có cơ hội hỏi liệu tôi có thể xoay 'Cast' thành tuân thủ điều hành của tôi. Xuất hiện không. :-) –

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