82

Possible Duplicate:
Why do I get “error: … must be a reference type” in my C# generic method?

I have 2 Repository methods that are almost identical:

public IList<Fund> GetFundsByName(int pageSize, string searchExpression)
{
    return _session.CreateCriteria<Fund>()
        .AddNameSearchCriteria<Fund>(searchExpression)
        .AddOrder<Fund>(f => f.Name, Order.Asc)
        .SetMaxResults(pageSize).List<Fund>();
}

public IList<Company> GetCompaniesByName(int pageSize, string searchExpression)
{
    return _session.CreateCriteria<Company>()
        .AddNameSearchCriteria<Company>(searchExpression)
        .AddOrder<Company>(f => f.Name, Order.Asc)
        .SetMaxResults(pageSize).List<Company>();
}

The only difference is that the first one's _session.CreateCriteria is of type Fund and the second one is company

I was hoping that I could make this generic by changing the method definition to:

public IList<T> GetEntitiesByName<T>(int pageSize, string searchExpression)
    where T : ISearchableEntity
{
    return _session.CreateCriteria<T>()
        .AddNameSearchCriteria<T>(searchExpression)
        .AddOrder<T>(f => f.Name, Order.Asc)
        .SetMaxResults(pageSize).List<T>();
}

where ISearchableEntity is defined as:

public interface ISearchableEntity
{
    string Name { get; set; }
}

but unfortunately NHibernate doesn't like this and gives me the error:

The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'NHibernate.ISession.CreateCriteria<T>()'

Is it possible for me to make this generic some other way?

Amit Joshi
  • 15,448
  • 21
  • 77
  • 141
DaveDev
  • 41,155
  • 72
  • 223
  • 385
  • Are `Fund` and `Company` Classes? – AllenG Jul 29 '10 at 17:05
  • @AllenG, yes, Fund & Company are classes – DaveDev Jul 29 '10 at 17:13
  • Could also possibly look at the CreateCriteria function sourcecode and see how they constrain it to a reference type and perhaps you could employ the same method to constrain your generic type to a reference type. – AaronLS Jul 29 '10 at 17:27
  • @AAronLS, `CreateCriteria` is defined in some NHibernate assemby or another, so I don't have access to the source – DaveDev Jul 29 '10 at 20:21
  • NHibernate is open source, here is the file for CreateCriteria which shows they use `where T : class;`: http://nhibernate.svn.sourceforge.net/viewvc/nhibernate/trunk/nhibernate/src/NHibernate/ISession.cs?revision=4868&view=markup – AaronLS Jul 29 '10 at 20:43
  • 2
    I love that earned "Notable Question" for this and it's been "closed as exact duplicate" for close to 2 years :-/ – DaveDev May 03 '12 at 15:23
  • 1
    As is frequently the case, it's only obvious these are the same question once you understand the answer. I call this multiple search vectors - different paths of enquiry leading to the same piece of understanding. The rule Nazis don't seem to think it's useful to support multiple search vectors. – Peter Wone Apr 28 '14 at 23:46

2 Answers2

212

You could try adding the constraint class:

where T : class, ISearchableEntity
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 4
    At first I assumed this only worked if T had to be a Class, but after looking at the page linked in theburningmonk's answer I found out that despite the name of this constraint, "this applies also to any class, interface, delegate, or array type." So use `where T : class` even if you need T to be an interface, as was my case. – Zach Esposito May 10 '16 at 18:04
  • This also works for struct – Jamie Nicholl-Shelley Sep 17 '17 at 01:14
29

Here's the full list of constraints you can use on T

http://msdn.microsoft.com/en-us/library/d5x73970.aspx

theburningmonk
  • 15,701
  • 14
  • 61
  • 104
  • NOTE: If one is calling a method and gets this error, Int32? (e.g.) will not work as a reference type, but the array Int32?[] will work as such! – JosephDoggie Dec 16 '14 at 20:29