我的同事宣称,在.NET 2.0及更新版本中声明变量,返回参数等时,永远不需要使用Object
。
他进一步说,在所有这些情况下,应该使用Generic作为替代。
此声明是否有效?我用Object
来锁定并发线程......
答案 0 :(得分:8)
泛型在很多情况下都会胜过object
,但只有在已知类型的地方。
有些时候你不知道类型 - object
,或者其他一些相关的基类型就是这些情况下的答案。
例如:
object o = Activator.CreateInstance("Some type in an unreferenced assembly");
您将无法在编译时投射该结果或者甚至不知道该类型是什么,因此object
是有效用途。
你的同事过于泛化 - 或许指出他在这个问题上。泛型是伟大的,给他那么多,但他们不“替换”object
。
答案 1 :(得分:3)
object
非常适合锁定。泛型允许您保持适当的输入。您甚至可以将其约束到接口或基类。你不能用object
。
考虑一下:
void DoSomething(object foo)
{
foo.DoFoo();
}
没有任何演员,这将无法奏效。但是用泛型......
void DoSomething<T>(T foo) where T : IHasDoFoo
{
foo.DoFoo();
}
使用C#4.0和dynamic
,您可以将其设置为运行时,但我确实没有看到需要。
void DoSomething(dynamic foo)
{
foo.DoFoo();
}
答案 2 :(得分:2)
当使用与COM的互操作时,你并不总是有选择......通用不能真正满足互操作的问题。
Object
也是lock
最轻量级的选项,@Daniel A. White中提及his answer。
答案 3 :(得分:1)
是的,有效性。已经进行了很好的细分here。
但是,我无法确认是否没有从不使用对象的实例,但我个人不使用它们,甚至在仿制药之前我避免装箱/拆箱。
答案 4 :(得分:0)
有许多反例,包括你提到的那个,使用对象进行同步。
另一个例子是数据绑定中使用的DataSource
属性,可以将其设置为各种不同对象类型之一。
答案 5 :(得分:0)
广泛的反例:System.Collections命名空间在.NET 4中运行良好,没有弃用或警告其在MSDN上使用的迹象。你在那里找到的方法采取并返回对象。
答案 6 :(得分:0)
问题中固有的实际上是两个问题:
Object
类型的存储位置显然必须用于需要保留对该类型实例的引用的任何情况(因为对此类实例的引用不能以任何其他类型保存)。除此之外,它们应该用于它们将保持对没有单一有用的公共基类型的对象的引用的情况。在使用Reflection(其中对象的类型可能依赖于在运行时计算的字符串)的许多场景中,这显然是正确的,但是也可以应用于某些种类的集合,这些集合填充有在编译时已知类型的事物。举一个简单的例子,可以通过让每个节点都为string
类型并使其保持int
来表示由Object
序列索引的String
层次集合。或Object[]
。从这样的集合中读出项目会有点笨拙,因为必须检查每个项目并确定它是Object[]
还是String
的实例,但是这样的存储方法会非常记忆 - 有效,因为唯一的对象实例是那些持有字符串或数组的对象实例。可以使用类型为Node
的字段和类型为String
的字段定义Node[]
类型,或者甚至定义具有派生类型Node
的抽象StringNode
类型(包括类型String
)和ArrayNode
的字段(带有Node[]
类型的字段),但这样的方法会增加用于保存给定数据集的堆对象的数量。
请注意,一般来说,最好设计集合,以便要检索的对象的类型不依赖于被塞入集合的内容(可能使用不同类型的“并行集合”),但并非所有内容都能解决在语义上。
关于Object
类型的实例,我不确定它们是否可以填充任何角色,这些角色不会被称为类似TokenObject
的密封类型所支持。 Object
。在许多情况下,拥有一个唯一目的是作为唯一令牌的对象实例是有用的。从概念上讲,它可能更好:
TokenObject myLock = new TokenObject;
而不是说
Object myLock = new Object;
因为前一个声明会清楚地表明声明的变量永远不会用于保存除标记对象之外的任何东西。尽管如此,通常的做法是使用Object
类型的实例,在这种情况下,关于该对象的唯一重要事项是它的引用在程序的整个生命周期中都是唯一的。