C#返回不同的types?
我有这样的东西:
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?! }
我有一个方法,这种方法有时会返回不同types的值(类)。
我怎么能做到这一点,当然以后的工作与variables,是radio.Play(); 到目前为止?
我需要使用generics吗? 怎么样?
如果没有公共基types或接口,那么public object GetAnything() {...}
– 但通常最好是具有某种抽象,如通用接口。 例如,如果Hello
, Computer
和Radio
都实现了IFoo
,那么它可以返回一个IFoo
。
下面是你如何用generics来做到这一点:
public T GetAnything<T>() { T t = //Code to create instance return t; }
但是你必须知道你想在devise时返回什么types。 这意味着你可以为每个创build调用不同的方法…
马克的答案应该是正确的,但在.NET 4中,你不能同时使用dynamictypes。
只有当你无法控制你返回的类并且没有共同的祖先时(通常使用interop),并且只有在不使用dynamic的时候,才会使用这个方法。
很less有博客文章试图解释何时使用dynamic: 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 }
如果你可以为所有的可能性做一个抽象类,那么强烈build议:
public Hardware GetAnything() { Computer computer = new Computer(); return computer; } abstract Hardware { } class Computer : Hardware { }
或者一个界面:
interface IHardware { } class Computer : IHardware { }
如果它可以是任何东西,那么你可以考虑使用“对象”作为你的返回types,因为每个类派生自对象。
public object GetAnything() { Hello hello = new Hello(); return hello; }
要使用genericsbuild立@RQDQ的答案,可以将其与Func<TResult>
(或一些变体)结合使用,并将责任委托给调用者:
public T GetAnything<T>(Func<T> createInstanceOfT) { //do whatever return createInstanceOfT(); }
然后你可以做一些事情:
Computer comp = GetAnything(() => new Computer()); Radio rad = GetAnything(() => new Radio());
您可以使返回types成为三个类的超类(由您定义或仅使用object
)。 然后你可以返回这些对象中的任何一个,但是在得到结果时你需要把它转换回正确的types。 喜欢:
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?! }
然后:
Hello hello = (Hello)getAnything();
你可以返回一个Object,因为所有types都是从Objectinheritance的。
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?! }
然后你可以转换成相关的types:
Hello hello = (Hello)GetAnything();
如果你不知道types是什么,那么你可以使用is
关键字。
Object obj = GetAnything(); if (obj is Hello) { // Do something }
这就是说我不愿意写这样的代码。 有一个由你的每个类实现的接口会好得多。
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(); }
并让你的每个类都实现这个接口:
public class Hello : ISpeak { void Speak() { Console.WriteLine("Hello"); } }
然后你可以做这样的事情:
GetAnything().Speak();
根据您要返回不同types的原因,您有几个选项。
a)你可以返回一个对象,调用者可以将它(可能在types检查之后)转换为他们想要的。 这当然意味着你失去了很多静态types的优点。
b)如果返回的types都有一个共同的“要求”,那么你可能会使用generics与constriants 。
c)在所有可能的返回types之间创build一个通用接口,然后返回接口。
d)切换到F#并使用模式匹配和区分的联合。 (对不起,稍微舌头检查!)
让方法从一个公共基类或接口返回一个对象。
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(); } }
里克的解决scheme是大多数情况下“最好的”方式。 有时候,当你不想使用对象作为基本types的时候。 你可以使用这样的方法:
public object GetAnything() { Hello hello = new Hello(); Computer computer = new Computer(); Radio radio = new Radio(); return hello; // or computer or radio }
要使用它,你会想要使用as
操作符,如下所示:
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 } }
在你的情况下,你想调用一个方法播放。 所以这似乎更合适:
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 }
我有一个想法返回多种types…….
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;} }
你可以使用外部类,根据需要设置属性types,然后在你的函数中使用它。
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; }
为所有人定义单一types并不总是可能的。 即使可以的话,实施也很难。 我更喜欢使用参数。 唯一需要注意的是,你需要知道所有的高级返回types:
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(); }
返回types可以是void
或其他types,比如bool
int
或预定义的enum
,这可以帮助您检查exception或不同情况,无论使用何种方法。
可能你需要“dynamic”types?
public dynamic GetAnything() { Hello hello = new Hello(); Computer computer = new Computer(); Radio radio = new Radio(); return /*what boject you needed*/ ;`enter code here` }