C#:System.Object vs Generics

for*_*yez 26 c# generics object

我很难理解何时使用Object(装箱/拆箱)与何时使用泛型.

例如:

public class Stack 
{
    int position;
    object[] data = new object[10];
    public void Push (object o) { data[position++] = o; }
    public object Pop() { return data[--position]; }
}
Run Code Online (Sandbox Code Playgroud)

VS.

public class Stack<T>
{ 
  int position; 
  T[] data = new T[100]; 
  public void Push(T obj)  {data[position++] = obj; }
  public T Pop() { return data[--position]; }
 }
Run Code Online (Sandbox Code Playgroud)

我应该使用哪一个以及在什么条件下?看起来像System.Object方式,我可以拥有当前生活在我的堆栈中的各种类型的对象.那么这总是不可取的吗?谢谢!

ill*_*ant 29

总是使用泛型!使用对象的结果进行强制类型的强制转换操作和装箱/拆箱.由于这些原因,仿制药更快更优雅(没有铸造).并且 - 主要原因 - 你不会InvalidCastException使用泛型.

因此,泛型更快,并且在编译时可以看到错误.System.Object表示运行时异常和转换,这通常会导致较低的性能(有时甚至更低).

  • 我对ALWAYS有点怀疑......所以我绝对没有使用'对象'的情况? (4认同)
  • 我的意思是每次都可以使用泛型,如果你真的需要在你的集合中存储多种类型,你可以简单地使用像List <object>这样的东西 (2认同)
  • 那么,“始终使用泛型”会留在哪里? (2认同)

Sof*_*mes 8

很多人都推荐使用泛型,但看起来他们都错过了这一点.它通常不是关于拳击原始类型或转换的性能命中,而是关于让编译器为你工作.

如果我有一个字符串列表,我希望编译器向我证明它将始终包含一个字符串列表.泛型就是这样 - 我指定了意图,编译器为我证明了这一点.

理想情况下,我更喜欢一个更丰富的类型系统,你可以说,例如一个类型(即使它是一个引用类型)不能包含空值,但遗憾的是C#目前不提供.


Hen*_*man 7

几乎总是想要使用泛型.

使用System.Object作为"常规类型"的应用程序:

  • 在旧的FX2之前的应用程序中,因为泛型不可用.
  • 当您需要混合不同的类型时,如在ASP.NET会话和应用程序对象中.

请注意,在您的第一个示例(非泛型)中,用法如下所示:

Stack s = ...;
s.Push("Hello");
s.Push(1.23);

double d = (double) s.Pop();
string t = (string) s.Pop();
Run Code Online (Sandbox Code Playgroud)

你真的想避免所有这些类型转换(为了可读性,安全性和性能).

  • 即使在混合类型时,使用T恰好是`object`的泛型集合也会让你几乎一样.它不会改善类型安全性,但它不会使情况变得更糟.它还意味着您可以直接使用LINQ方法,而无需调用扩展方法`IEnumerable.Cast <object>()` (3认同)

tva*_*son 6

虽然有时您会想要使用非泛型集合(例如,想想缓存),但您几乎总是拥有同质对象的集合而不是异构对象.对于同源集合,即使它是基本类型或接口变体的集合,使用泛型总是更好.这样可以避免在使用之前将结果转换为真实类型.使用泛型可以使代码更高效和可读,因为您可以省略代码来执行强制转换.


Sha*_*ard 5

这完全取决于您的长期需求。

与这里的大多数答案不同,我不会说“始终使用仿制药”,因为有时您确实需要将猫与黄瓜混合。

无论如何,出于其他答案中已经给出的所有原因,请尝试坚持使用泛型,例如,如果您需要将猫和狗结合起来创建基类 Mammal 并拥有Stack<Mamal>.

但是,当您确实需要支持每种可能的类型时,不要害怕使用对象,除非您虐待它们,否则它们不会咬人。:)