C# 泛型最酷的地方是什么,为什么要使用它们?

C# 泛型最酷的地方是什么,为什么要使用它们?,c#,generics,types,C#,Generics,Types,我想我会把这个垒球送给任何想把它打出公园的人。什么是泛型,泛型的优点是什么,为什么,在哪里,我应该如何使用它们?请保持它相当基本。谢谢。泛型允许您创建强类型的对象,但不必定义特定类型。我认为最有用的例子是列表和类似的类 使用泛型列表,您可以拥有任何您想要的列表,并且您可以始终引用强类型,您不必转换或像使用数组或标准列表那样进行任何转换。泛型避免装箱和取消装箱的性能影响。基本上,看看ArrayList vs List。两者的核心功能相同,但列表速度会快得多,因为您不必在对象之间设置框。泛型允许您对

我想我会把这个垒球送给任何想把它打出公园的人。什么是泛型,泛型的优点是什么,为什么,在哪里,我应该如何使用它们?请保持它相当基本。谢谢。

泛型允许您创建强类型的对象,但不必定义特定类型。我认为最有用的例子是列表和类似的类


使用泛型列表,您可以拥有任何您想要的列表,并且您可以始终引用强类型,您不必转换或像使用数组或标准列表那样进行任何转换。

泛型避免装箱和取消装箱的性能影响。基本上,看看ArrayList vs List。两者的核心功能相同,但列表速度会快得多,因为您不必在对象之间设置框。

泛型允许您对对象和数据结构使用强类型,这些对象和数据结构应该能够容纳任何对象。在从泛型结构(装箱/取消装箱)检索对象时,它还消除了繁琐而昂贵的类型转换


使用这两种方法的一个例子是链表。如果链表类只能使用对象Foo,那么它有什么好处?要实现可处理任何类型对象的链表,如果希望链表仅包含一种类型的对象,则假定节点内部类中的链表和节点必须是泛型的。

如果集合包含值类型,当插入到集合中时,它们不需要对对象进行装箱/取消装箱,因此性能会显著提高。像resharper这样很酷的附加组件可以为您生成更多的代码,比如foreach循环。

我喜欢它们,因为它们为您提供了一种快速定义自定义类型的方法(因为我一直在使用它们)

例如,不必定义一个由字符串和整数组成的结构,然后必须实现一整套对象和方法来访问这些结构的数组等等,您只需制作一个字典

Dictionary<int, string> dictionary = new Dictionary<int, string>();
Dictionary Dictionary=newdictionary();
编译器/IDE完成了其余的繁重工作。字典特别允许您使用第一种类型作为键(无重复值)。

  • 允许您编写代码/使用类型安全的库方法,即列表保证为字符串列表
  • 由于使用了泛型,编译器可以对代码执行编译时检查,以确保类型安全,也就是说,您是否试图将int放入该字符串列表中?使用ArrayList会导致运行时错误不那么透明
  • 比使用对象更快,因为它可以避免装箱/取消装箱(其中.net必须转换)或从对象强制转换为所需的引用类型
  • 允许您编写适用于具有相同底层行为的许多类型的代码,即字典使用与字典相同的底层代码;使用泛型,框架团队只需编写一段代码即可实现上述两种结果

正如Mitchel指出的那样,主要优势是不需要定义多个类就可以进行强类型化

通过这种方式,您可以执行以下操作:

List<SomeCustomClass> blah = new List<SomeCustomClass>();
blah[0].SomeCustomFunction();
List blah=newlist();
blah[0]。SomeCustomFunction();

如果没有泛型,您必须将blah[0]强制转换为正确的类型才能访问其函数。

jvm仍然强制转换。。。它隐式地创建将泛型类型视为“对象”的代码,并创建所需实例化的强制转换。Java泛型只是语法上的糖。

使用泛型(尤其是集合/列表)的另一个优点是可以进行编译时类型检查。这在使用通用列表而不是对象列表时非常有用。

最主要的原因是它们提供了类型安全性

List<Customer> custCollection = new List<Customer>;

作为一个简单的例子。

总之,泛型允许您更精确地指定要执行的操作(更强的键入)

这对您有几个好处:

  • 因为编译器更了解您想要做什么,它允许您省略很多类型转换,因为它已经知道类型将是兼容的

  • 这也会让你更早地得到关于你的程序的正确性的反馈。以前在运行时会失败的事情(例如,因为无法将对象转换为所需的类型),现在在编译时失败,您可以在测试部门提交一份神秘的错误报告之前修复错误

  • 编译器可以进行更多优化,如避免装箱等


需要添加/扩展的内容(从.NET的角度讲):

泛型类型允许您创建基于角色的类和接口。这已经用更基本的术语讲过了,但我发现您开始使用以类型无关的方式实现的类来设计代码,这导致了代码的高度可重用性

关于方法的一般性论点也可以做同样的事情,但它们也有助于将“告诉-不要问”原则应用于铸造,即“给我我想要的,如果你不能,你告诉我为什么”。

我知道这是一个C#问题,但也在其他语言中使用,它们的用途/目标非常相似

Java集合从Java1.5开始使用。因此,当您创建自己的类似集合的对象时,可以使用它们

我几乎到处都能看到的一个例子是Pair类,它包含两个对象,但需要以通用的方式处理这些对象

class Pair<F, S> {
    public final F first;
    public final S second;

    public Pair(F f, S s)
    { 
        first = f;
        second = s;   
    }
}  
类对{
公开决赛F-first;
公开决赛第二名;
公共对(F、S、S)
{ 
第一个=f;
秒=秒;
}
}  
无论何时使用这个Pair类,您都可以指定希望它处理哪种类型的对象,并且任何类型转换问题都将在编译时而不是运行时出现

泛型也可以用关键字“super”和“extends”定义其边界。例如,如果你想要dea
class Pair<F, S> {
    public final F first;
    public final S second;

    public Pair(F f, S s)
    { 
        first = f;
        second = s;   
    }
}  
public class FooManager <F extends Foo>{
    public void setTitle(F foo, String title) {
        foo.setTitle(title);
    }
}
public interface IEntity
{

}

public class Employee : IEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int EmployeeID { get; set; }
}

public class Company : IEntity
{
    public string Name { get; set; }
    public string TaxID { get; set }
}

public class DataService<ENTITY, DATACONTEXT>
    where ENTITY : class, IEntity, new()
    where DATACONTEXT : DataContext, new()
{

    public void Create(List<ENTITY> entities)
    {
        using (DATACONTEXT db = new DATACONTEXT())
        {
            Table<ENTITY> table = db.GetTable<ENTITY>();

            foreach (ENTITY entity in entities)
                table.InsertOnSubmit (entity);

            db.SubmitChanges();
        }
    }
}

public class MyTest
{
    public void DoSomething()
    {
        var dataService = new DataService<Employee, MyDataContext>();
        dataService.Create(new Employee { FirstName = "Bob", LastName = "Smith", EmployeeID = 5 });
        var otherDataService = new DataService<Company, MyDataContext>();
            otherDataService.Create(new Company { Name = "ACME", TaxID = "123-111-2233" });

    }
}
public abstract class GenericDaoHibernateImpl<T> 
    extends HibernateDaoSupport {

    private Class<T> type;

    public GenericDaoHibernateImpl(Class<T> clazz) {
        type = clazz;
    }

    public void update(T object) {
        getHibernateTemplate().update(object);
    }

    @SuppressWarnings("unchecked")
    public Integer count() {
    return ((Integer) getHibernateTemplate().execute(
        new HibernateCallback() {
            public Object doInHibernate(Session session) {
                    // Code in Hibernate for getting the count
                }
        }));
    }
  .
  .
  .
}
public class UserDaoHibernateImpl extends GenericDaoHibernateImpl<User> {
    public UserDaoHibernateImpl() {
        super(User.class);     // This is for giving Hibernate a .class
                               // work with, as generics disappear at runtime
    }

    // Entity specific methods here
}
List<Stuff> stuffList = getStuff();
for(Stuff stuff : stuffList) {
    stuff.do();
}
List stuffList = getStuff();
Iterator i = stuffList.iterator();
while(i.hasNext()) {
    Stuff stuff = (Stuff)i.next();
    stuff.do();
}
List stuffList = getStuff();
for(int i = 0; i < stuffList.size(); i++) {
    Stuff stuff = (Stuff)stuffList.get(i);
    stuff.do();
}
public class Foo
{
   public string Bar() { return "Bar"; }
}
Arraylist al = new ArrayList();
List<Foo> fl = new List<Foo>();

//code to add Foos
al.Add(new Foo());
f1.Add(new Foo());
foreach(object o in al)
{
    Foo f = (Foo)o;
    f.Bar();
}

foreach(Foo f in fl)
{
   f.Bar();
}
class MyObjectList  {
   MyObject get(int index) {...}
}
class MyOtherObjectList  {
   MyOtherObject get(int index) {...}
}
class AnotherObjectList  {
   AnotherObject get(int index) {...}
}
class MyList<T> {
   T get(int index) { ... }
}
private <T extends Throwable> T logAndReturn(T t) {
    logThrowable(t); // some logging method that takes a Throwable
    return t;
}
    ...
} catch (MyException e) {
    throw logAndReturn(e);
}
...
Map<String, Integer> myMap = createHashMap();
...
public <K, V> Map<K, V> createHashMap() {
    return new HashMap<K, V>();
}
Map<String, Integer> m = new HashMap<String, Integer>();
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(42);

int total = 0;
for (int i : set) {
  total += i;
}
set.add(10);
set.add(42);
for (int i : set) {
  total += i;
}
Set set = new HashSet();
set.add(10);
set.add(42);

int total = 0;
for (Object o : set) {
  total += (Integer)o;
}
set.add(10);
set.add(42);
for (Object o : set) {
  total += (Integer)o;
public interface F<A, B> {
  public B f(A a);
}
F<Integer, String> intToString = new F<Integer, String>() {
  public String f(int i) {
    return String.valueOf(i);
  }
}
public final class Hash<A> {
  private final F<A, Integer> hashFunction;

  public Hash(final F<A, Integer> f) {
    this.hashFunction = f;
  }

  public int hash(A a) {
    return hashFunction.f(a);
  }
}
public interface Foo<T extends MyObject> extends Hoo<T>{
    ...
}
public <T extends MyObject> foo(T t1, T t2){
    ...
}