2012-01-24 39 views
37

tôi có một cái gì đó như thế này:C# Trả về các loại khác nhau?

public [What Here?] GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return radio; or return computer; or return hello //should be possible?!  
} 

Tôi có một phương pháp và phương pháp này trả về cho tôi loại đôi khi khác nhau của giá trị (lớp).

Làm cách nào tôi có thể thực hiện việc này và sau đó làm việc với các biến, b.e radio.Play(); và cho đến nay?

Tôi có cần dùng thuốc generic không? Làm sao?

+1

Xem http://stackoverflow.com/questions/1048884/c-overriding-return-types cho một vấn đề tương tự và một giải pháp. Tuy nhiên, tôi phải trung thực, trong đó tôi nghĩ rằng bạn có một vấn đề thiết kế nếu bạn đang làm điều này; nếu bạn đã xác định các loại thì có thể cấu trúc mã của bạn mà không cần điều này. – dash

+0

bạn có thể trả về 'đối tượng' và sau đó truyền kết quả, hoặc sử dụng phương pháp chung – balexandre

+1

Vấn đề thực tế bạn đang cố giải quyết là gì? – RQDQ

Trả lời

36

Nếu không có loại cơ sở chung hoặc giao diện, thì public object GetAnything() {...} - nhưng thường sẽ thích hợp hơn nếu có một loại trừu tượng như giao diện chung. Ví dụ: nếu Hello, ComputerRadio tất cả được triển khai IFoo, thì nó có thể trả lại IFoo.

+0

được không, cảm ơn bạn! – eMi

3

Bạn có thể có kiểu trả về là lớp cha của ba lớp (do bạn xác định hoặc chỉ sử dụng object). Sau đó, bạn có thể trả lại bất kỳ một trong những đối tượng đó, nhưng bạn sẽ cần phải đưa nó trở lại đúng loại khi nhận được kết quả. Giống như:

public object GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return radio; or return computer; or return hello //should be possible?!  
} 

Sau đó:

Hello hello = (Hello)getAnything(); 
+0

okay cảm ơn bạn! – eMi

+0

Điều này làm việc thực sự tốt, miễn là bạn không cần phải làm bất kỳ tài liệu tham khảo trở lại một "đối tượng" được lưu trữ bên trong phương pháp đó. Ví dụ cố gắng trả về một đối tượng đã tồn tại mà không cần tạo một đối tượng mới có thể là một thách thức. – ooXei1sh

10

Nếu bạn có thể làm cho một lớp trừu tượng cho tất cả các khả năng sau đó là rất khuyến khích:

public Hardware GetAnything() 
{ 
    Computer computer = new Computer(); 

    return computer;  
} 

abstract Hardware { 

} 

class Computer : Hardware { 

} 

Hoặc một giao diện:

interface IHardware { 

} 

class Computer : IHardware { 

} 

Nếu nó có thể là bất cứ điều gì n bạn có thể xem xét việc sử dụng "đối tượng" làm kiểu trả về của bạn, bởi vì mỗi lớp xuất phát từ đối tượng.

public object GetAnything() 
{ 
    Hello hello = new Hello(); 

    return hello;  
} 
29

Đây là cách bạn có thể làm điều đó với Generics:

public T GetAnything<T>() 
{ 
    T t = //Code to create instance 

    return t; 
} 

Nhưng bạn sẽ phải biết những gì loại bạn muốn quay trở lại vào thời điểm thiết kế. Và điều đó có nghĩa là bạn chỉ có thể gọi một phương pháp khác cho mỗi sáng tạo ...

-2

Có thể bạn cần loại "động"?

public dynamic GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return /*what boject you needed*/ ;`enter code here` 
} 
+0

Đây là ** không ** những gì năng động là một cách sử dụng chính xác cho. Năng động chỉ là một wrapper lạ mắt xung quanh sự phản chiếu, và được sử dụng cho các đối tượng thực sự năng động. Không cho các kịch bản hướng đối tượng đơn giản. – Aidiakapi

10

Câu trả lời của Marc phải đúng, nhưng trong .NET 4 bạn cũng không thể đi theo kiểu động.

Điều này chỉ nên sử dụng nếu bạn không có quyền kiểm soát lớp bạn quay trở lại và không có tổ tiên chung (thường là với interop) và chỉ khi không sử dụng động thì sẽ đau đớn hơn nhiều. bậc thang :)).

Rất ít bài viết trên blog cố gắng để giải thích khi nào sử dụng năng động: http://blogs.msdn.com/b/csharpfaq/archive/tags/dynamic/

public dynamic GetSomething() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 
    return // anyobject 

} 
+0

Thực ra, bạn có thể làm tốt mà không có từ khóa động. Cũng giống như các tiểu bang bình luận khác của tôi. Đây không phải là kịch bản mà bạn sử dụng động. – Aidiakapi

+0

@Aidiakapi Tôi biết bạn có thể làm điều đó mà không có động, đó là lý do tại sao tôi thêm dòng thứ hai của câu trả lời của tôi. Ví dụ, bạn có thể có một vấn đề tương tự bằng cách sử dụng văn bản interop động có thể giúp bạn tiết kiệm rất nhiều tổ hợp phím :) – tburi

+0

Dynamic có sử dụng nó, nhưng hầu hết mọi người nhìn thấy nó như là một từ khóa huyền diệu, và lạm dụng nó . (Giống như trong ví dụ này.) Nó nên tránh bất cứ nơi nào có thể. – Aidiakapi

1

Bạn có một vài lựa chọn tùy thuộc vào lý do tại sao bạn muốn trở lại các loại khác nhau.

a) Bạn chỉ có thể trả về một đối tượng và người gọi có thể truyền đối tượng (có thể sau khi kiểm tra loại) đến những gì họ muốn. Điều này có nghĩa là tất nhiên, bạn sẽ mất rất nhiều lợi thế khi gõ tĩnh.

b) Nếu các loại trả về đều có 'yêu cầu' chung, bạn có thể sử dụng generics with constriants.

c) Tạo giao diện chung giữa tất cả các loại trả về có thể và sau đó trả về giao diện.

d) Chuyển sang F # và sử dụng pattern matching và các công đoàn bị phân biệt đối xử. (Xin lỗi, hơi lưỡi trong kiểm tra ở đó!)

+0

Lol, hoặc bạn có thể vào C++ và sử dụng 'void *'>. <, Tôi nghi ngờ anh ta muốn sử dụng bất kỳ ngôn ngữ lập trình nào khác ngoài những gì anh ta hỏi. – Aidiakapi

+0

Đó là lý do tại sao tùy chọn này d. Có nói rằng, tôi đã có một số dự án có một cơ sở mã F #/C# hỗn hợp; mỗi ngôn ngữ đều có điểm mạnh riêng. – mavnn

+0

Tôi đồng ý, giống như C++/CLI, cũng có thể được chia sẻ trong các dự án. Tuy nhiên tôi nghĩ rằng nó khá không liên quan đến câu hỏi. (Đừng hiểu lầm tôi, tôi thích F #, nó rất tuyệt cho những trường hợp rất cụ thể.) – Aidiakapi

1

Cho phép phương thức trả về một đối tượng từ một baseclass hoặc giao diện chung.

public class TV:IMediaPlayer 
{ 
    void Play(){}; 
} 

public class Radio:IMediaPlayer 
{ 
    void Play(){}; 
} 

public interface IMediaPlayer 
{ 
    void Play(): 
} 

public class Test 
{ 
    public void Main() 
    { 
    IMediaPlayer player = GetMediaPlayer(); 
    player.Play(); 
    } 


    private IMediaPlayer GetMediaPlayer() 
    { 
    if(...) 
     return new TV(); 
    else 
     return new Radio(); 
    } 
} 
2

Bạn chỉ có thể trả về một đối tượng vì tất cả các loại đều xuất phát từ Object.

public Object GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return radio; or return computer; or return hello //should be possible?!  
} 

Sau đó, bạn có thể cast vào loại có liên quan của nó:

Hello hello = (Hello)GetAnything(); 

Nếu bạn không biết những gì các loại sẽ là sau đó bạn có thể sử dụng từ khóa is.

Object obj = GetAnything(); 
if (obj is Hello) { 
    // Do something 
} 

Điều này đang được nói là tôi không muốn viết mã như thế. Sẽ tốt hơn nếu bạn có một giao diện được thực hiện bởi từng lớp của bạn.

public ISpeak GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return radio; or return computer; or return hello //should be possible?!  
} 

interface ISpeak 
{ 
    void Speak(); 
} 

và đã từng lớp học của bạn thực hiện các giao diện:

public class Hello : ISpeak 
{ 
    void Speak() { 
     Console.WriteLine("Hello"); 
    } 
} 

Sau đó bạn có thể làm điều gì đó như:

GetAnything().Speak(); 
1

giải pháp của Rick là 'tốt nhất' con đường để đi trong hầu hết các các trường hợp. Đôi khi khi không có sẵn, bạn muốn sử dụng đối tượng làm kiểu cơ sở. Và bạn có thể sử dụng các phương pháp như thế này:

public object GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return hello; // or computer or radio 
} 

Để sử dụng nó, bạn sẽ muốn sử dụng các nhà điều hành as, như thế này:

public void TestMethod() 
{ 
    object anything = GetAnything(); 
    var hello = anything as Hello; 
    var computer = anything as Computer; 
    var radio = anything as Radio; 

    if (hello != null) 
    { 
     // GetAnything() returned a hello 
    } 
    else if (computer != null) 
    { 
     // GetAnything() returned a computer 
    } 
    else if (radio != null) 
    { 
     // GetAnything() returned a radio 
    } 
    else 
    { 
     // GetAnything() returned... well anything :D 
    } 
} 

Trong trường hợp của bạn, bạn muốn gọi một vở kịch phương pháp. Vì vậy, điều này có vẻ thích hợp hơn:

interface IPlayable 
{ 
    void Play(); 
} 

class Radio : IPlayable 
{ 
    public void Play() { /* Play radio */ } 
} 

class Hello : IPlayable 
{ 
    public void Play() { /* Say hello */ } 
} 

class Computer : IPlayable 
{ 
    public void Play() { /* beep beep */ } 
} 

public IPlayable GetAnything() 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 

    return hello; // or computer or radio 
} 
0

Bạn có thể sử dụng lớp bên ngoài, đặt loại thuộc tính như bạn muốn, sau đó sử dụng các loại thuộc tính của bạn.

public class MultipleOpjects 
{ 
    private List<string> _ObjectOne; 
    public List<string> ObjectOne { 
     get { return _ObjectOne; } 
     set { _ObjectOne = value; } 
    } 
    private List<object> _ObjectTwo; 
    public List<object> ObjectTwo { 
     get { return _ObjectTwo; } 
     set { _ObjectTwo = value; } 
    } 
    private object _ObjectThree; 
    public object ObjectThree { 
     get { return _ObjectThree; } 
     set { _ObjectThree = value; } 
    } 
} 
public MultipleOpjects GetAnything() 
{ 
    MultipleOpjects Vrble = new MultipleOpjects(); 
    Vrble.ObjectOne = SomeThing1; 
    Vrble.ObjectTwo = SomeThing2; 
    Vrble.ObjectThree = SomeThing3; 

    return Vrble;  
} 
5

Để xây dựng dựa trên câu trả lời của @RQDQ sử dụng Generics, bạn có thể kết hợp này với Func<TResult> (hoặc một số biến thể) và ủy thác trách nhiệm cho người gọi:

public T GetAnything<T>(Func<T> createInstanceOfT) 
{ 
    //do whatever 

    return createInstanceOfT(); 
} 

Sau đó, bạn có thể làm như sau:

Computer comp = GetAnything(() => new Computer()); 
Radio rad = GetAnything(() => new Radio()); 
0

tôi có một ý tưởng trả lại nhiều loại .......

public object GetAnything(object o) 
{ 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 
    if(o == Hello){return hello;} 
    if(o == Computer {return computer;} 
    if(o == Radio) {return radio;} 
} 
+0

Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ [danh tiếng] (http://stackoverflow.com/help/whats-reputation), bạn sẽ có thể [nhận xét về bất kỳ bài đăng nào] (http://stackoverflow.com/help/privileges/comment); thay vào đó, [cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi] (http://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-thay thế). - [Từ đánh giá] (/ review/low-quality-posts/12733494) – Johan

+2

Hey câu trả lời của tôi làm việc cho tôi người đàn ông .... Bạn cần phải xác nhận tại các chức năng gọi điện thoại bằng cách có một cái gì đó như thế này var a = GetAnything (đối tượng o) if (a.GetType() == typeof (Computer) {} else if (a.GetType() == typeof (Xin chào) {} else if (a.GetType() == typeof (Radio) {} –

0

Xác định một loại duy nhất cho tất cả không phải lúc nào cũng có thể. Ngay cả khi bạn có thể, việc thực hiện hiếm khi dễ dàng. Tôi thích sử dụng thông số out. Thông báo trước duy nhất là bạn cần phải biết tất cả các loại trở lại trong tiên tiến:

public void GetAnything(out Hello h, out Computer c, out Radio r) 
{ 
    /// I suggest to: 
    h = null; 
    c = null; 
    r = null; 
    // first, 

    // Then do whatever you have to do: 
    Hello hello = new Hello(); 
    Computer computer = new Computer(); 
    Radio radio = new Radio(); 
} 

các kiểu trả về có thể là một void, hay cái gì khác, giống như bool một int hay được xác định trước enum có thể giúp bạn kiểm tra các trường hợp ngoại lệ hoặc các trường hợp khác nhau bất cứ khi nào phương pháp được sử dụng.

0

sử dụng từ khóa động làm loại trả lại.

private dynamic getValuesD<T>() 
    { 
     if (typeof(T) == typeof(int)) 
     { 
      return 0; 
     } 
     else if (typeof(T) == typeof(string)) 
     { 
      return ""; 
     } 
     else if (typeof(T) == typeof(double)) 
     { 
      return 0; 
     } 
     else 
     { 
      return false; 
     } 
    } 

     int res = getValuesD<int>(); 
     string res1 = getValuesD<string>(); 
     double res2 = getValuesD<double>(); 
     bool res3 = getValuesD<bool>(); 

regards,

Abhijit

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