C# ';为什么';和';其中';是否实际使用了泛型?

C# ';为什么';和';其中';是否实际使用了泛型?,c#,.net,generics,C#,.net,Generics,我知道泛型是用来实现类型安全的,我经常读到它们主要用于定制集合。但为什么我们真的需要通用呢 比如说, 为什么我不能使用string[]而不是List 让我假设一个泛型类,它有一个泛型类型参数x.< /p> T x; 如果我为类提供一个方法 x = x + 1; 这到底是什么意思?我不知道t实际将是什么,也不知道x=x+1实际将执行什么 如果我不能在我的方法中进行我自己的操作,那么泛型将如何帮助我呢 我已经研究了很多书生气的答案。如果有人能在这方面提供一些清晰的见解,我们将不胜感激 问候,,

我知道泛型是用来实现类型安全的,我经常读到它们主要用于定制集合。但为什么我们真的需要通用呢

比如说,

为什么我不能使用
string[]
而不是
List

让我假设一个泛型类,它有一个泛型类型参数x.< /p>

T x;
如果我为类提供一个方法

x = x + 1;
这到底是什么意思?我不知道
t
实际将是什么,也不知道
x=x+1
实际将执行什么

如果我不能在我的方法中进行我自己的操作,那么泛型将如何帮助我呢

我已经研究了很多书生气的答案。如果有人能在这方面提供一些清晰的见解,我们将不胜感激

问候,,
NLV

当我们需要“高阶”多态性时,我们使用泛型,类似于编译时。当我们说
Foo
时,我们的意思是
Foo
依赖于任何可能的
T
可以具有的某些属性,并且给定的
T
具有该属性,或者代码无法编译

当我们说
x=x+1
时,我们意味着
T
能够添加
1
,返回类型是
T

但为什么我们真的需要通用呢

如果您愿意,还可以创建许多自定义类:
StringList
IntList
DoubleList
,等等。。但是泛型的要点是,您可以定义一次类,它适用于所有对象


x=x+1
其中
x
是泛型
T
需要实际的实数类型来支持或自然添加int,或者让
操作符+
重载int作为第二种类型。

对于第一个问题,您可以选择
List
而不是
string[]
如果要向列表中动态添加字符串-数组的大小是固定的。

因为虽然支持字符串[](即扣除自定义数组类型),但数组具有: *功能不如列表,甚至不如IList *是数组,因此这不适用于其他类型的集合。字典呢

如果我不能自己做 我的方法中的操作 仿制药会帮助我的 无论如何

这有点像问“如果我经营一家素食餐厅,我能在我的供应商那里买到牛排有什么好处?”

基本上,当项目变得更复杂时,您将在方法中编写自己的操作。你会在有意义的地方做所有的事情。

public foobar{
public foobar<T>{
    public Action<string,T> SomeAction;
    public string SomeString;
    public foobar(Action<string,T> s,string m){
         SomeAction=s;
         SomeString=m;
    }


    public void Run(T foo){
         SomeAction(SomeString,foo);
    }
}
公共行动; 公共字符串SomeString; 公共foobar(动作s,字符串m){ SomeAction=s; SomeString=m; } 公众假期跑步(T-foo){ SomeAction(SomeString,foo); } }

如果没有泛型,您将不得不为每种可能的情况编写不同的类,或者进行一些其他精细的操作以获得所需的结果。泛型让事情变得更优雅。

事实上,我正在一个atm网站上工作,在那里泛型让我的工作更轻松。我需要从数据库访问大量信息,因为整个站点都是数据库驱动的,所以我真的希望有一个类来实现数据库功能。这个类被更多知道如何处理各自数据的类继承

例如,我有一个处理产品数据的Products类和一个处理主题的Themes类,等等。,。所有这些课程都需要一种通用的阅读和写作格式。所以,我创建了一个记录类来处理这个问题

现在,泛型的乐趣从这里开始。我创建了一个产品类、主题类等。,。对于强类型成员,例如Name、Manufacturer、ThemeId,Records类不知道如何处理它们。因此,数据库类被实例化为与特定类、产品、主题等相关的类型。,。Record类也使用泛型类型,因此我可以编写如下代码

Product.Name = "Cool Product";
然后把它像

Products.InsertRecord(Product coolProduct);
它不仅节省了大量的输入,而且使我能够拥有一个处理所有脏活的类,而这些小的“存根”类为我提供了一个可读的强类型接口


不管怎样,我为这篇冗长的文章感到抱歉。希望这至少能帮助您理解泛型在这种情况下的威力。

string[]
为我们提供了一个固定大小的数组。要获得动态大小的列表,我们需要一个类。因此,如果我们想要一个字符串列表,我们可能必须创建一个名为StringList的类。双打,双打名单。等等但是,这些类对于这些类型来说是唯一的呢?没有什么。因此,我们创建了一个泛型类List,它可以接受任何类型。泛型不必为不同的类型一次又一次地重新创建同一个类,它为我们节省了一些工作

至于
x=x+1
问题,您必须预期T有一个
+
操作符,它在右侧接受int。如果没有,它将抛出一个运行时错误。如果是,则该代码将把x分配给
+
运算符的输出,并将
x
1
作为参数

在许多其他情况下,没有执行唯一的操作,并且类/方法必须处理多个类型。在这些情况下,泛型也很重要和有用


在代码中何时何地使用它们实际上取决于您自己。如果你遇到一个问题,他们是最好的答案,很好。使用它们。否则,不要。只是不要取消它们作为解决方案的资格,因为它们从来都不是您特定问题的答案。

根据我自己的工作经验,管理Linq到SQL类型就是一个很好的例子。创建网元时必须执行的一个基本操作
public class SQLObjectManager<TEntity> where TEntity : class, new()
{
    public TEntity GetObject(int year, int stateID)
    {
        if( /* entity found in cache */)
            return GetFromCache(year,stateID);
        if( /* entity found in db */)
            return GetFromDB(year,stateID);
        TEntity entity = new TEntity();
        entity.Year = year;
        entity.StateID = stateID;
        return entity;
    }
}
MyGenericStack<string> stringStack = new MyGenericStack<string>();
stringStack.Push("One");
stringStack.Push("Two");
stringStack.Push("Three");

MyGenericStack<int> intStack = new MyGenericStack<int>();
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);

MyGenericStack<CustomObject> customObjectStack = new MyGenericStack<CustomObject>();
customObjectStack.Push(new CustomObject(1));
customObjectStack.Push(new CustomObject(2));
customObjectStack.Push(new CustomObject(3));
public class MyGenericStack<T>
{
    int position;
    T[] data = new T[10];
    public void Push(T obj) { data[position++] = obj; }
    public T Pop() { return data[--position]; }

    public void Show()
    {

        for (int i = 0; i < data.Length; i++)
        {
            //Console.WriteLine("Item: {0}", data[i]);
            //MessageBox.Show(String.Format("Item: {0}", data[i]));
        }
    }
}