Generics在性能和利弊方面给了我一些优势吗

本文关键字:性能 方面 Generics | 更新日期: 2023-09-27 17:58:20

我正在尝试生成一些方法,如下所示,添加crmhuman resources。但我想写Crm、人力资源、供应链等(5-6模块)如何简单地写下面的代码(下面的代码是骨架:)我先是在没有泛型的情况下写作,然后又用泛型写作。第二种用法与第一种用法不同。1) 清晰的读数也可管理和消耗
2) 给我一些性能优势。无装箱和拆箱过程

你能教我泛型的优缺点吗?比较第一和第二用法?


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace App.GenericsBaseClass.Diff
{
    // View : 
    class Program
    {
        static void Main(string[] args)
        {
            new Crm().Add("Yapı Kredi");
            Console.Read();
            new HumanResources().Add("yusuf karatoprak");
            Console.Read();
        }
    }
  // Business
    public class Crm : Customer
    {
        public override void Add(object obj)
        {
            if (obj is String)
            {
                base.Add(obj);
            }
            else
            {
                throw new InvalidOperationException("Customer Name must be string Format...");
            }
        }
    }
    public class HumanResources : Staff
    {
        public override void Add(object obj)
        {
            if (obj is string)
            {
                base.Add(obj);
            }
            else
            {
                throw new InvalidOperationException("Stuff Name must be string Format...");
            }
        }
    }
    // Dal
    public class Staff
    {
        public virtual void Add(object obj)
        {
            new Db.Staff().Save((string)obj);
        }
    }
    public class Customer
    {
        public virtual void Add(object obj)
        {
            new Db.Customer().Save((string)obj);
        }
    }
    // Model
    public class Db
    {
        public class Customer
        {
            public void Save(string Name)
            {
                Console.WriteLine("Customer : {0} is saved",Name);
            }
        }
        public class Staff
        {
            public void Save(string Name)
            {
                Console.WriteLine("Staff: {0} is saved", Name);
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace App.GenericsInstadofBaseMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            new Crm<string>().Add("Yapı Kredi");
            Console.Read();
            new HumanResources<string>().Add("yusuf karatoprak");
            Console.Read();
        }
    }
    // Business
    public class Crm<T> : Customer<T>
    {
        public override void Add(T obj)
        {
                base.Add(obj);
        }
    }
    public class HumanResources<T> : Staff<T>
    {
        public override void Add(T obj)
        {
                base.Add(obj);
        }
    }
    // Dal
    public class Staff<T>
    {
        public virtual void Add(T obj)
        {
            new Db<T>.Staff().Save(obj);
        }
    }
    public class Customer<T>
    {
        public virtual void Add(T obj)
        {
            new Db<T>.Customer().Save(obj);
        }
    }
    // Model
    public class Db<T> 
    {
        public class Customer
        {
            public void Save(T Name)
            {
                Console.WriteLine("Customer : {0} is saved", Name.ToString());
            }
        }
        public class Staff
        {
            public void Save(T Name)
            {
                Console.WriteLine("Staff: {0} is saved", Name);
            }
        }
    }
}

Generics在性能和利弊方面给了我一些优势吗

据我所知,Generic的大多数操作都发生在IL级别,因此性能不会受到太大影响(如果有的话)。它所做的只是强制并检查对象是否属于某一类型。最大的缺点是对方差和协方差的理解。这里有一些关于它的文章。

文章

在通用集合的接口中使用方差

协方差和方差常见问题解答(.NET 4.0更新版)

优点

使用泛型,您可以在运行时和设计时获得类型安全性。您能够实时接收有关对象的智能感知,就好像它们是为特定类型硬编码的一样。这在设置扩展方法和…时非常有用。。。嗯,几乎所有其他的东西。事实上,从那以后。NET 2.0,我甚至不再使用非泛型列表,除非类型只是object

  • 编辑

正如其他人指出的那样,这就避免了开箱的必要性。

Cons

由于逆方差和协方差的不同性质,有时会混淆在泛型中什么是可接受的,什么是不可接受的。例如,如果您考虑以下布局。。

interface IBase {
}
class Alpha : IBase {
}
class Beta : Alpha {
}
IList<IBase> ListOfObjects { get; set; }

这令人困惑。可以将AlphaBeta对象都传递到列表中吗?当我尝试的时候,你做不到。但随后,以下措施奏效了。。

IList<Alpha> ListOfObjects { get; set; }

它同时接受AlphaBeta对象,因为Beta继承了Alpha

在这里查看更多关于反方差和协方差的信息。它非常有用。

我从未注意到泛型对性能的影响。然而,这并不意味着它们不存在。然而,它们只是普通的物体,所以我看不出哪里会有头顶。一般来说,编译器甚至不应该让你在试图向泛型列表中添加不正确对象的地方运行代码,如果这样做了,那么你在某个地方犯了设计错误,或者正在使用dynamics,或者遇到了方差与协方差的问题。尽管我确实理解其中的一些已经改变了。NET 4.0。

除了我的文章解释了一些关于泛型的东西之外,您在这里的情况看起来根本不需要它们。您应该改为向类中添加一个属性。

public class Person {
   public string Name { get; set; }
}
public class Customer : Person {
}
public class Staff : Person {
}
public class HumanResources : Staff {
}
public class Db {
  public List<Customer> Customers { get; set; }
  public List<Staff> Staff { get; set; }
}
public static void Main(){ 
  var db = new Db {
     Customers = new List<Customer> { },
     Staff = new List<Staff> { }
  };
  Db.Customers.Add(new Customer { Name = "Primary Customer" } );
  Db.Staff.Add(new Staff { Name = "Employee Prime" } );
  Db.Staff.Add(new HumanResources { Name = "Human Resource Manager" });
}

泛型应该用于坚持进入的类型,而不是实际控制数据。您所举的例子并没有以真正的预期方式使用泛型。

在本例中,创建一个基类,然后创建三个子类型,其中一个子类型继承自另一个子类型。因此,CustomerStaffDb(假设它是数据库的缩写)接受的两个主要类型。

Db可以采用Customer的列表和Staff的列表,因为HumanResourcesStaff的一种类型,所以可以将它们存储在一起。您还可以添加一个List<Person> People { get; set; },它将接受所有类型,因为它们不可避免地会相互继承。

至于强制字符串,最好在构造函数中执行。

public class Person { 
   public Person(string name) { 
      this.Name = name; }
   }
   public string Name { get; private set; }
}

在这个例子中,我们设置了Name字段,这样它就可以被所有人看到,但只能在创建时更改和设置(这不是最好的想法,但它证明了这一点)。

现在,您可以添加一个新的Customer,如下所示。。

Db.Customers.Add( new Customer ( "Ciel" ) );或新员工。。。Db.Staff.Add( new Staff( "Darin" ) );

我认为性能差异不大。

通过使用泛型,您真正获得的是对类型的编译时检查。例如,它可以防止您传递错误类型的对象(在这种情况下,如果您期望特定类型,则使用object参数会导致运行时错误)。

泛型是关于类型安全的imho。你可以编写更健壮的代码,因为你会得到编译时的错误,而不是运行时的试用&恐怖

拳击是一种奖励,但你不应该仅仅为了避免拳击而选择泛型(这听起来像是过早的优化)。

在这里,您可以找到一个关于使用泛型的优点和缺点的非常有趣的视频。