Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net net中泛型的实际使用(框架中的泛型除外)_.net_Generics - Fatal编程技术网

.net net中泛型的实际使用(框架中的泛型除外)

.net net中泛型的实际使用(框架中的泛型除外),.net,generics,.net,Generics,我知道这个理论,它们非常棒,框架中包含的那些简化了很多事情,它们甚至有性能增益。 关于这个主题,有很多答案,都有很好的例子,但通常对我来说实用价值很低,或者框架中已经有了一些例子。 问题是,在哪些情况下,您决定编写自己的类来使用泛型?每当类对尚未定义的类型执行一组操作时,我都使用泛型 例如,假设您实现了一组数学运算,但希望类的用户能够确定实际的数字类型int,short。。。。通过使泛型不指定类型,泛型类可以得到更广泛的使用 另一个相关的好处是,为泛型类生成的代码实际上更加具体,例如使用较少的强

我知道这个理论,它们非常棒,框架中包含的那些简化了很多事情,它们甚至有性能增益。 关于这个主题,有很多答案,都有很好的例子,但通常对我来说实用价值很低,或者框架中已经有了一些例子。
问题是,在哪些情况下,您决定编写自己的类来使用泛型?

每当类对尚未定义的类型执行一组操作时,我都使用泛型

例如,假设您实现了一组数学运算,但希望类的用户能够确定实际的数字类型int,short。。。。通过使泛型不指定类型,泛型类可以得到更广泛的使用


另一个相关的好处是,为泛型类生成的代码实际上更加具体,例如使用较少的强制转换操作和可能较少的运行时测试。NET framework中的泛型容器就是一个很好的例子。

每当类对尚未定义的类型执行一组操作时,我都使用泛型

例如,假设您实现了一组数学运算,但希望类的用户能够确定实际的数字类型int,short。。。。通过使泛型不指定类型,泛型类可以得到更广泛的使用


另一个相关的好处是,为泛型类生成的代码实际上更加具体,例如使用较少的强制转换操作和可能较少的运行时测试。NET framework中的泛型容器就是一个很好的例子。

每当我需要在不同类型的对象上应用相同的算法/相同的逻辑时,我都会使用泛型

例如,通用存储库:

public interface IRepository<T> where T : class, IEntity
{
  IQueryable<T> GetQuery();
  void Update(T entity);
  void Insert(T entity);
  void Delete(int id);
}

public interface IEntity
{
  int Id { get; set; }
}

每当我需要在不同类型的对象上应用相同的算法/相同的逻辑时,我都会使用泛型

例如,通用存储库:

public interface IRepository<T> where T : class, IEntity
{
  IQueryable<T> GetQuery();
  void Update(T entity);
  void Insert(T entity);
  void Delete(int id);
}

public interface IEntity
{
  int Id { get; set; }
}

哇-太多的例子可能太复杂,无法快速给出答案。。。我能给你的

我在很多地方使用泛型,尤其是总结应用于许多场景的常见模式。然而,我提到的最有益的用途之一是加速基于反射或其他动态代码的速度,这些代码将根据操作数的类型而变化,同时将其隐藏起来

例如,一个虚构的例子,因为我的真实世界的例子太复杂和抽象,没有太多的背景,让我们假设我有一个组件,它使用字符串几乎完全从对象检索数据值。当然,如果它执行了一次或两次,则不成问题,保留反射,但如果它执行了很多次,则您要做的是编译动态委托,以便更快地检索值。所以

public static class NamedValueAccessor<T>
{
  private Dictionary<string, Func<T, object>> _accessors;
  private Dictionary<string, Action<T, object>> _writers;

  public object GetValue(T instance, string name) { }
  public void SetValue(T instance, string name, object newValue) { }
}
因为它没有约束,所以可以应用于所有类型

如果你只有一个对象,也可以通过反射——你可以使用它的GetType方法来获取运行时类型,执行一个typeofNamedValueAccessor.MakeGenericTypeo.GetType.GetMethod….调用。。。。但是,按照相同的模式,在本例中,最好为每个类型构建委托的动态缓存,这些委托在传入类型的正确NamedValueAccessor.GetValue方法上烘焙

更新

因此,为了解释在本例中泛型为我们做了什么:

1如果在编译时已知泛型类型参数,即NamedValueAccessor.GetValueFoo编译到泛型的特定实例,则编译器将解析基于类型的属性缓存。在运行时要做的就是在字典中查找委托并执行它

2不同类型的缓存分开存放

3可以在静态类的静态构造函数中启动缓存,并对类型进行简单的反射,以获得支持的所有属性,并预编译所有委托。当然,您必须小心使用此代码,以确保它不会引发运行时错误-没有人喜欢TypeInitializationException。如果您这样做,那么您也不必担心多线程环境——缓存是不可变的

在第3点,如果类型是一个idynamico对象,那么这个策略当然会失败,但是您可以委托给实例的动态接口

结束更新

在实践中,我使用它是为了做比包装属性setter和getter更复杂的事情,ComponentModel命名空间中的代码可能更适合这样做——正如Mvc利用它的方式一样,但是,适当地编织这些类型的解决方案为最终用户(在我的例子中是应用程序编码人员)提供了优异的性能和可访问性

我也希望这个答案过于抽象,无法获得任何投票,但我还是把它扔出去了,因为我们不提供答案来获得投票,而是通知提问者:

哇-太好了 许多例子可能太复杂,无法快速给出答案。。。我能给你的

我在很多地方使用泛型,尤其是总结应用于许多场景的常见模式。然而,我提到的最有益的用途之一是加速基于反射或其他动态代码的速度,这些代码将根据操作数的类型而变化,同时将其隐藏起来

例如,一个虚构的例子,因为我的真实世界的例子太复杂和抽象,没有太多的背景,让我们假设我有一个组件,它使用字符串几乎完全从对象检索数据值。当然,如果它执行了一次或两次,则不成问题,保留反射,但如果它执行了很多次,则您要做的是编译动态委托,以便更快地检索值。所以

public static class NamedValueAccessor<T>
{
  private Dictionary<string, Func<T, object>> _accessors;
  private Dictionary<string, Action<T, object>> _writers;

  public object GetValue(T instance, string name) { }
  public void SetValue(T instance, string name, object newValue) { }
}
因为它没有约束,所以可以应用于所有类型

如果你只有一个对象,也可以通过反射——你可以使用它的GetType方法来获取运行时类型,执行一个typeofNamedValueAccessor.MakeGenericTypeo.GetType.GetMethod….调用。。。。但是,按照相同的模式,在本例中,最好为每个类型构建委托的动态缓存,这些委托在传入类型的正确NamedValueAccessor.GetValue方法上烘焙

更新

因此,为了解释在本例中泛型为我们做了什么:

1如果在编译时已知泛型类型参数,即NamedValueAccessor.GetValueFoo编译到泛型的特定实例,则编译器将解析基于类型的属性缓存。在运行时要做的就是在字典中查找委托并执行它

2不同类型的缓存分开存放

3可以在静态类的静态构造函数中启动缓存,并对类型进行简单的反射,以获得支持的所有属性,并预编译所有委托。当然,您必须小心使用此代码,以确保它不会引发运行时错误-没有人喜欢TypeInitializationException。如果您这样做,那么您也不必担心多线程环境——缓存是不可变的

在第3点,如果类型是一个idynamico对象,那么这个策略当然会失败,但是您可以委托给实例的动态接口

结束更新

在实践中,我使用它是为了做比包装属性setter和getter更复杂的事情,ComponentModel命名空间中的代码可能更适合这样做——正如Mvc利用它的方式一样,但是,适当地编织这些类型的解决方案为最终用户(在我的例子中是应用程序编码人员)提供了优异的性能和可访问性


我还认为这个答案过于抽象,无法获得任何投票,但我还是把它扔了出去,因为我们不提供获得投票的答案,而是告诉提出问题的人:

我使用泛型向实现两个接口的对象添加扩展方法,所以

public static MyExtension<T>(this T myobject) where T : ISomeInterface, ISomeOtherInterface
{
   //Do some stuff on myObject
}

我使用泛型向实现几个接口的对象添加了一个扩展方法,所以

public static MyExtension<T>(this T myobject) where T : ISomeInterface, ISomeOtherInterface
{
   //Do some stuff on myObject
}

读一本关于面向对象的书。你似乎跳过了关于模式的一章,把工厂作为最简单的例子。读了一本关于面向对象的书。你似乎跳过了关于模式的一章,把工厂作为最简单的例子。这是一个很好的论点,不是一个真正实用的例子,但仍然非常实用!我使用泛型实现了点和向量类,并对这些类进行了代码处理几何操作。执行时间在很大程度上取决于存储类型8位、16位、浮点,使用哪种类型取决于应用程序。通过使用泛型,我总是可以确保为特定的应用程序使用最好的代码。@丹尼尔:是的,它是实用的,我在.NET中丢失的唯一的是数字的基数类型,这样我就可以限制Type类向量,其中T:数字。@ Ladislav:是的,这是与C++模板相比的一个主要缺点。请参阅,以获得至少部分此功能的解决方法。@Daniel Gehriger:虽然框架本机不支持此功能,但有一个简单的解决方法。看看这个博客:。这是一个很好的论点,不是一个真正的实际例子,但仍然非常实用!我使用泛型实现了点和向量类,并对这些类进行了代码处理几何操作。执行时间在很大程度上取决于存储类型8位、16位、浮点,使用哪种类型取决于应用程序。通过使用泛型,我总是可以确保为特定的应用程序使用最好的代码。@丹尼尔:是的,它是实用的,我在.NET中丢失的唯一的是数字的基数类型,这样我就可以限制Type类向量,其中T:数字。@ Ladislav:是的,这是与C++模板相比的一个主要缺点。请参阅以获得至少部分此功能的解决方法。@Daniel Gehriger:
虽然框架本身不支持,但有一个简单的解决方法。请看这篇博客:。这也是DLR的核心内容,尽管其背后的缓存和逻辑比我在这里建议的要深入得多,所以我知道您使用这种技术通过让编译器分解泛型类中的代码来提高性能,克里斯蒂安打算在评论中回答,而不是使用反思,对吗;但我认为最好在答案中添加额外的信息,给出一些理由。这也是DLR的核心内容,尽管背后的缓存和逻辑比我在这里建议的要深入得多,所以我理解您使用这种技术通过让编译器分解泛型类中的代码来提高性能,而不是使用反射,对吗?@Cristian-将在一篇评论中回答;但我认为最好在答案中添加额外的信息,并给出一些理由。哦,F中的自动泛型尽可能地符合人性。哦,F中的自动泛型尽可能符合人性。