2011-01-31 26 views
6

thể trùng lặp:
Why can't I use interface with explicit operator?Tại sao C# không cho phép các loại sử dụng bố cục để có chuyển đổi ngầm cho giao diện?

Khi tôi làm điều này:

public struct Effect 
{ 
    public IEffect IEffect { get; private set; } 

    public Effect (IEffect effect) 
    { 
     this.IEffect = effect; 
    } 

    public static implicit operator IEffect (Effect effect) 
    { 
     return effect.IEffect; 
    } 

    public static explicit operator Effect (IEffect effect) 
    { 
     return new Effect (effect); 
    } 
} 

tôi nhận được một lỗi biên dịch như thế này:

'ImageEditor.Effect .imp nhà điều hành licit ImageEditor.IEffect (ImageEditor.Effect) ': chuyển đổi do người dùng xác định đến hoặc từ giao diện không được phép.

Tại sao chúng không được phép? Đây không phải là một thực hành tốt?

+0

Bản sao có thể có của: http://stackoverflow.com/questions/2433204/why-cant-i-use-interface-with-explicit-operator –

Trả lời

7

Điều này được trình bày chi tiết trong phần 10.10.3 của thông số ngôn ngữ C#.

Lý do tóm tắt các lý do tại sao mặc dù là ...

  • nhà khai thác chuyển đổi không nên thay thế built-in chuyển đổi. Cho phép điều này chỉ dẫn đến hành vi cực kỳ khó hiểu
  • Nói chung nó không thể xác định nếu một chuyển đổi ngầm để một giao diện được thay thế một built-in chuyển đổi và do đó nó không được phép
+0

Cảm ơn Jared, trong lý do thứ hai của bạn, bởi "không thể" bạn có nghĩa là bởi trình biên dịch hoặc người dùng để xác định? Tôi cho rằng đó là người dùng. –

+0

Lý do chủ yếu là nếu một đối tượng có thể được chuyển đổi thành IOneInterface và ITwoInterface, thì tham chiếu của đối tượng thông qua IOneInterface sẽ được chuyển thành ITwoInterface. Các toán tử ghi đè có thể phá vỡ điều này. (ít nhất đó là sự hiểu biết của tôi) –

+1

@Janan không thể đề cập đến khả năng của trình biên dịch để đưa ra quyết định này. Lưu ý: nó được giới hạn trong trường hợp chung vì có các trường hợp cụ thể (các lớp 'struct' và' sealed') trong đó trình biên dịch có thể đưa ra quyết định này. Nhưng nhóm C# đã quyết định chống lại điều này (vì lý do tại sao tôi chỉ có thể suy đoán nhưng phỏng đoán của tôi là nhất quán) – JaredPar

1

Lý do chính là một đối tượng mà thực hiện một giao diện luôn luôn chuyển đổi hoàn toàn thành lớp cơ sở của nó, và luôn luôn chuyển đổi rõ ràng từ lớp cơ sở của nó thành chính nó. Đó là dư thừa và khó hiểu để ghi đè hành vi này, và bạn không thể ghi đè lên tất cả các hành vi cần thiết để làm cho nó hoạt động đúng, và do đó nó không được phép. Trong trường hợp của bạn, bạn đang ghi đè một số nhưng không phải là tất cả hành vi thừa kế. Ví dụ: phương pháp hay nhất khi đúc một cách rõ ràng là:

IEffect anIEffectInstance = GetEffectAsInterface(); 

if(anIEffectInstance is Effect) //<--you cannot override this behavior to return true, 
    var interfaceAscConcrete = (Effect)anIEffectInstance; //<-- so this overridden code would never execute 
0

Âm thanh như câu hỏi cho Jon Skeet hoặc tương tự, nhưng tôi sẽ chụp ảnh đó.

Toán tử ngầm mà bạn đã mô tả sẽ phần lớn không cần thiết. Nếu Effect đã triển khai IEffect, bạn có thể sử dụng Effect ở bất kỳ nơi nào bạn cần đối tượng triển khai IEffect mà không làm phiền đến chuyển đổi do người dùng xác định.

Sự cố nhà điều hành rõ ràng có thể mang tính triết học hơn một chút. Sự hiểu biết của tôi là điểm của các chuyển đổi tiềm ẩn và rõ ràng là chuyển đổi một đối tượng của một kiểu thành một đối tượng của một kiểu khác mà mối quan hệ của họ chưa rõ ràng với trình biên dịch vì một lý do nào đó. Tuy nhiên, một giao diện không phải là một đối tượng. Người ta không thể khởi tạo trực tiếp giao diện; thay vào đó, giao diện cần được thực hiện bởi một số lớp. Khi bạn sử dụng chuyển đổi ngầm hoặc rõ ràng, đối tượng kết quả không được liên kết theo loại cho đối tượng trước đó. Điều đó có nghĩa là đối tượng phát sinh từ việc chuyển đổi cần phải có khả năng đứng độc lập và có một kiểu đối tượng thực tế, mà chính giao diện của chính nó thì không.

Có lẽ trực tiếp hơn: Loại kết quả cụ thể của kết quả của chuyển đổi tiềm ẩn là gì? Trình biên dịch không có cách nào để biết, vì vậy nó không thể khởi tạo đối tượng.

Nếu bạn thực sự cần làm điều gì đó như thế này, bạn sẽ muốn tạo một lớp cơ sở trừu tượng triển khai giao diện. Sau đó, bạn sẽ có thể "chuyển đổi" thành và từ lớp cơ sở trừu tượng, mà nó có một kiểu đối tượng.

+0

Cảm ơn nhưng Hiệu ứng không thực hiện IEffect. –

+0

@Janan Venge Bạn được chào đón, nhưng không nên thực thi IEffect? Những gì bạn đang cố gắng thực hiện được phục vụ bởi mô hình nhà nước? (Tóm tắt: http://en.wikipedia.org/wiki/State_pattern) Tóm lại, bạn sẽ triển khai IEffect với Effect và sử dụng các phương thức và thuộc tính của IEffect được lưu trữ để triển khai IEffect trong lớp Effect. – Andrew

+0

Cảm ơn, không bao giờ nghe mô hình tiểu bang, nhưng IEffect này là một trình bao bọc cho một API không được quản lý. Vì vậy, tôi đang sử dụng bố cục chứ không phải thừa kế vì nó có nhiều yếu tố mà tôi không muốn triển khai và hiển thị cho người dùng API của mình. –

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