views:

209

answers:

6

I'm getting the error "T does not contain a definition for Id" below in the specified line, even though when I debug, I see that "item" does indeed have a property "Id" in its base class.

How do I specify here that I want C# to look in the item's base class for Id (and why doesn't it do this automatically?)?

//public abstract class Items<T> : ItemBase (causes same error)
public abstract class Items<T> where T : ItemBase
{
    public List<T> _collection = new List<T>();
    public List<T> Collection
    {
        get
        {
            return _collection;
        }
    }

    public int GetNextId()
    {
        int highestId = 0;
        foreach (T item in _collection)
        {
           //ERROR: "T does not contain a definition for Id
           if (item.Id > highestId) highestId = item.Id; 
        }

        return highestId;
    }

}

Here's how the classes are being defined:

public class SmartForm : Item
{
    public string IdCode { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public int LabelWidth { get; set; }
    public int FormWidth { get; set; }
    ...


public abstract class Item : ItemBase
{
    public int Id { get; set; }
    public DateTime WhenCreated { get; set; }
    public string ItemOwner { get; set; }
    public string PublishStatus { get; set; }
    public int CorrectionOfId { get; set; }
    ...
+4  A: 

You got your generic constraint wrong.

public abstract class Items<T> : ItemBase

should be:

public abstract class Items<T> where T : ItemBase

What happened is that while your class has a collection of items, your ItemBase is not associated with T

Jon Limjap
A: 

this might help :-)

   foreach (ItemBase item in _collection)
    {
       if (item.Id > highestId) highestId = (Item)item.Id; 
    }
Ratnesh Maurya
if compilation error try typecasting to ItemBase
Ratnesh Maurya
tells me a "converstion from type T to Itembase" is not possible
Edward Tanguay
+12  A: 

Your problem is that there is no constraint on T, so, at compile time, all the compiler knows is that T is some sort of object. If you know what type T will always inherit off, you can add a generic constraint to the class definition:

public abstract class Items<T> : ItemBase where T : Item
{
//....
}

When you're debugging, T is instantiated to an Item (or subclass of) that does have an Id property, but the compiler doesn't know that at compile time, hence the error.

thecoop
beautiful, thanks.
Edward Tanguay
I don't get it... why does Items<T> inherit from ItemBase?
Daren Thomas
Every item in my application has a singular and plural class, so e.g. User --> Item --> ItemBase, and Users --> Items --> ItemBase where ItemBase has protected methods which both the singular and plural model classes use such as ApplicationDataPath FullXmlDataStorePathAndFileName and HandleXmlFileNotFound, etc.
Edward Tanguay
+1  A: 

You have to specify that T is always derived from ItemBase using a where clause.

Timbo
+4  A: 

Because T could be absolutely anything, and C# is meant to be type-safe. Use a constraint on T to a type which has an id property, and you should be OK. See here for more info.

Vinay Sajip
+1  A: 

You accidentally let Items inherit ItemBase, instead of T inheriting ItemBase. Just change

: ItemBase

to

where T : ItemBase
Dykam
I changed "public abstract class Items<T> : ItemBase" to "public abstract class Items<T> where T : ItemBase" and I get the same error, changed code above.
Edward Tanguay