设计多种类型对象的最佳方法假设我有一个数据对象,但是这个对象可以包含几种数据类型中的一种。类Foo{intintFoo;双双福;字符串字符串;现在,我想创建一个访问器。获取这些数据的一些方法。显然,我可以创建多个访问器:publicintGetIntFoo();公共双GetDoubleFoo();公共字符串GetStringFoo();或者我可以创建多个属性publicintIntFoo{get;放;}publicdoubleDoubleFoo{得到;放;}公共字符串StringFoo{得到;放;我不认为这是一个很好的设计。它要求客户端代码比它应该更关心类型。更重要的是,我真的只需要这个类的单个值,上面将允许同时分配每个类型之一。不好。一种选择是使用泛型。classFoo{publicTTheFoo{get;放;然而,这并没有创建Foo,而是创建了一个Foo。每个都有不同的类型,所以我不能真正将它们用作同一类型。我可以从FooBase派生Foo并将它们全部视为FooBase,但随后我又回到访问数据的状态。一个不同的通用选项是使用这样的东西:classFoo{stringstringRepresentationOfFoo;publicTGetFoo(){return/*stringtotype*/}}问题当然是任何类型的T都可以传,说实话有点忙。我也可以只插入值并返回一个对象,但没有类型安全。理想情况下,我想对所有Foos执行相同的操作,但我希望类型安全,这样我什至无法编译对没有StringFoo的StringFoo的引用。Foofoo=newFoo("Foo");字符串sFoo=foo.Value;//成功。富富=新富(0);intiFoo=foo.Value;//成功stringsFoo=foo.Value;//编译错误也许这是不可能的……我将不得不做出一些妥协,但也许我遗漏了一些东西。有任何想法吗?编辑:好吧,正如丹尼尔指出的那样,运行时类型的编译时检查是不切实际的。做我想做的事情的最佳选择是什么?也就是说,对所有的Foo都一视同仁,但仍然有一个相对健全的访问机制?EDIT2:我不想将值转换为不同的类型。我想返回值的正确类型。也就是说,如果它是双精度型,我不想返回一个整数。如何将变量作为参数传递给获取?像这样:inti=foo.get(i);然后在你的课堂上,你会有这样的东西:publicintget(intp){if(this.type!=INTEGER)thrownewRuntimeException("Datatypemismatch");返回this.intVal;}publicfloatget(floatp){if(this.type!=FLOAT)thrownewRuntimeException("Datatypemismatch");返回this.floatVal;这种类型的内部输出转换类型:不是检查foo拥有什么类型,而是让foo检查你想要什么类型。如果它可以为您提供该类型,那么它会抛出运行时异常。我不认为这会起作用(给你你想要的编译器错误)你想做什么:Foobar=(newRandom()).Next(2)==0?newFoo("bar"):newFoo(1);intbaz=bar.Value;这是编译器错误吗?我认为“一视同仁”(至少以您描述的方式)和“编译时错误”是相互排斥的。无论如何,我认为“最好的方法”是泛型和继承之间的折衷。你可以定义Foo,它是Foo的子类;那么你仍然可以拥有Foo的集合。abstractpublicclassFoo{//公共实现abstractpublicobjectObjectValue{get;}}publicclassFoo:Foo{publicFoo(TinitialValue){Value=initialValue;}公共T值{得到;放;}publicobjectObjectValue{get{返回值;}}}许多系统使用辅助方法来返回替代类型,例如.net框架基础对象有一个ToString()方法来选择哪个是每个对象的最佳基础类型,并为其他情况提供To类等方法Foo{公共Int32值{得到;放;}publicByteToByte(){returnConvert.ToByte(Value);}publicDoubleToDouble(){return(Double)Value;}publicnewStringToString(){returnValue.ToString("#,###");一件事是在类的内部状态中存储任何类型,另一件事是在外部公开它。当你编写一个类时,你实际上是在为其行为声明一个契约。您编写它的方式将极大地影响您的客户端代码在使用该类时的外观。例如,通过实现IConvertible接口,您可以声明您的类型作为等效类型可转换为任何CLR类型。我还见过使用Value类存储计算结果的实现,它可以表示字符串、双精度数、整数或布尔值。但是,问题是客户端代码必须检查枚举{String,Integer,Double,Boolean}的Value.Type属性,然后强制转换Value.Value属性(由Value类在外部公开为Object类型)或使用特定的ValueString、ValueDouble、ValueInt、ValueBooleangetter。为什么不使用string、double和int?关于收集的信息:使用对象怎么样?无论如何,您将不得不检查类型等。为了帮助您,您可以使用is和as运算符。和Enumerable.Cast方法,或者更好的Enumerable.OfType方法。实际上,这个类的目的是什么?最大的问题似乎是设计至少打破了SRP(单一职责原则)。尽管如此,如果我没看错的话,您还是希望在容器中存储一些值,将容器传递给客户端并以类型安全的方式检索值。通过这种方法,您可以使用您的建议,namespaceProject1{publicclassClass1{staticintMain(string[]args){Fooa=newFoo();a.设置值(4);Console.WriteLine(a.GetValue());Foob=newFoo();a.SetValue("字符串");Console.WriteLine(a.GetValue());控制台.ReadLine();返回0;}}classFoo{私有对象值;//注意这里的拳击!publicvoidSetValue(objectvalue){this.value=value;}publicTGetValue(){objectval=this.value;如果(val==null){返回默认值(T);}//或者如果你喜欢抛出try{return(T)val;}catch(Exception){返回默认值(T);//转换失败,返回default(T)或抛出}}}}但是,在这种情况下,为什么不简单地将数据作为对象传递并自己转换呢?根据您的需要,您还可以尝试“C#中的PHP”:namespaceProject1{publicclassClass1{staticintMain(string[]args){MyInta=1;MyIntb="2";控制台.WriteLine(a+b);//写入3Console.ReadLine();返回0;}}类MyInt{私有int值;publicstaticimplicitoperatorint(MyIntcontainer){返回内容内部价值;}publicstaticimplicitoperatorMyInt(intvalue){MyIntmyInt=newMyInt();myInt.value=值;返回我的整数;}publicstaticimplicitoperatorMyInt(stringstringedInt){MyIntmyInt=newMyInt();myInt.value=int.Parse(stringedInt);返回我的整数;对不起,我只是不相信你的前提,如果数据都服务于相同的目的,那么它们应该都具有相同的类型。考虑一个旨在维持当前温度的类,该类由多个Web服务之一返回。所有服务都以摄氏度返回。但是一个返回一个int,一个返回一个double,一个返回一个字符串。这不是三种不同的类型-它是一种类型-双。您只需要将非双精度返回转换为双精度,即温度(或浮点数)。一般来说,如果你对一个事物有多种表示,它仍然是一个事物,而不是很多。将多个表示转换为一个。以上就是《C#学习教程:设计多种对象的最佳方式》分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。涉及侵权,请点击维权联系管理员删除。如需转载请注明出处:
