Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

T does not contain the definition for RowKey

I am trying to create a generic class:

public class ClassName<T>
{
    public T AccessEntity(string id)
    {
        return (from e in ServiceContext.CreateQuery<T>(TableName)
                where e.RowKey == id // error here!
                select e).FirstOrDefault();
    }
}

In this code I am getting error that:

T does not contain the definition for RowKey

but the parameters which will replace the T at runtime have the definition of RowKey. Maybe because complier is not getting the definition for RowKey in T at compile time, that`s why I am getting this error. Can anybody tell me how to solve this issue?

like image 295
Tom Rider Avatar asked Jul 23 '12 14:07

Tom Rider


4 Answers

To do that you would need an interface constraint:

interface IHazRowKey {
     string RowKey { get; } 
}

And specify this restriction:

public class classname<T> where T : IHazRowKey {...}

And specify : IHazRowKey on each of the implementations:

public class Foo : IHazRowKey {....}

The existing RowKey member should match it (assuming it is a property, not a field), so you shouldn't need to add any other extra code. If it is actually a field (which it shouldn't be, IMO) then:

public class Foo : IHazRowKey {
    string HazRowKey.RowKey { get { return this.RowKey; } }
    ...
}
like image 113
Marc Gravell Avatar answered Nov 15 '22 16:11

Marc Gravell


There is a major difference between C++ templates and C# generics: it does not matter what classes you pass to instantiate the generic, if the compiler does not know about a method on T at the time of compiling your generic class or method, it would give you an error. This is because C# needs an ability to compile the generic code separately from its places of instantiation (remember, there are no headers in C#).

You can define an interface, and restrict T to it in order to use properties and methods inside a generic. Add RowKey to your interface, and add where T : myinterface to your generic declaration.

like image 45
Sergey Kalinichenko Avatar answered Nov 15 '22 14:11

Sergey Kalinichenko


You need to define constraint to solve this:

public interface IHasRowKey
{
   string RowKey {get;}
}

public class classname<T> where T : IHasRowKey
{

}
like image 3
Aliostad Avatar answered Nov 15 '22 15:11

Aliostad


class YourClass // or extract an interface
{
    public string RowKey { get; set; }
}

class YourGeneric<T> where T : YourClass
{
    // now T is strongly-typed class containing the property requested
}
like image 1
abatishchev Avatar answered Nov 15 '22 15:11

abatishchev