FrozenHeart FrozenHeart - 1 month ago 10
C# Question

How to pass C# generic type to another class

Is there any way to write the following code in C#?

public T GetRandomRecord<T>(DbSet<T> set)
{
return set.OrderBy(r => Guid.NewGuid()).FirstOrDefault();
}


It gives me the following error:


Error CS0452 The type 'T' must be a reference type in order to use it
as parameter 'TEntity' in the generic type or method 'DbSet'


DbSet
is the
Microsoft.EntityFrameworkCore.DbSet
.

How can I fix it?

Answer

Try a generic type constraint. class in this context will constrain T to be a reference type. Callers won't be able to call GetRandomRecord<DateTime>(dbSet), because DateTime is a struct. This will be enforced by the compiler.

public T GetRandomRecord<T>(DbSet<T> set) where T : class
{
    // ... stuff
}

This is required because DBSet<TEntity> has the same constraint:

public class DbSet<TEntity> 
    : DbQuery<TEntity>, 
      IDbSet<TEntity>, 
      IQueryable<TEntity>, 
      IEnumerable<TEntity>, 
      IQueryable, 
      IEnumerable 
      where TEntity : class
    //  M... O... U... S... EEEEE....
{

So the compiler won't let you do what you're doing until you can guarantee that you will respect that constraint that DbSet has. You provide that guarantee by applying the same constraint to your own method, which passes it along to your callers.