Uses for static generic classes?

前端 未结 9 1720
猫巷女王i
猫巷女王i 2020-12-08 10:11

What are the key uses of a Static Generic Class in C#? When should they be used? What examples best illustrate their usage?

e.g.

         


        
相关标签:
9条回答
  • 2020-12-08 10:54

    A static generic class is exactly as useful as any given static class. The difference is that you don't have to use copy-and-paste to create a version of the static class for each type you want it to work on. You make the class generic, and you can "generate" one version for each set of type parameters.

    0 讨论(0)
  • 2020-12-08 10:56

    I use static generic classes for caching reflection-heavy code.

    Let's say I need to build an expression tree that instantiates objects. I build it once in the static constructor of the class, compile it to a lambda expression, then cache it in a member of the static class. I often don't make these classes publicly assessable - they are usually helpers for other classes. By caching my expressions in this way, I avoid the need to cache my expressions in some sort of Dictionary<Type, delegate>.

    There is an example of this pattern in the BCL. The (DataRow) extension methods Field<T>() and SetField<T>() use the (private) static generic class System.Data.DataRowExtensions+UnboxT<T>. Check it out with Reflector.

    0 讨论(0)
  • 2020-12-08 11:02

    I use these to mock a DbSet when testing against classes that use EntityFramework Async methods.

    public static class DatabaseMockSetProvider<TEntity> where TEntity: class
    {
        public static DbSet<TEntity> CreateMockedDbSet(IQueryable<TEntity> mockData)
        {
            var mockSet = Mock.Create<DbSet<TEntity>>();
            Mock.Arrange(() => ((IDbAsyncEnumerable<TEntity>)mockSet).GetAsyncEnumerator())
                .Returns(new TestDbAsyncEnumerator<TEntity>(mockData.GetEnumerator()));
            Mock.Arrange(() => ((IQueryable<TEntity>)mockSet).Provider)
                .Returns(new TestDbAsyncQueryProvider<TEntity>(mockData.Provider));
            Mock.Arrange(() => ((IQueryable<TEntity>)mockSet).Expression).Returns(mockData.Expression);
            Mock.Arrange(() => ((IQueryable<TEntity>)mockSet).ElementType).Returns(mockData.ElementType);
            Mock.Arrange(() => ((IQueryable<TEntity>)mockSet).GetEnumerator()).Returns(mockData.GetEnumerator());
    
            return mockSet;
        }
    }
    

    And use them like so in my unit tests - saves a lot of time and can use them for any entity types:

    var mockSet = DatabaseMockSetProvider<RecipeEntity>.CreateMockedDbSet(recipes);
            Mock.Arrange(() => context.RecipeEntities).ReturnsCollection(mockSet);
    
    0 讨论(0)
提交回复
热议问题