0

I don't understand what am I doing wrong when trying to access members of class from generic type T. I also specifically used WHERE constraint. I get the following message: 'T' is a type parameter, which is not valid in the current context.

class Test
{
    public static int id = 1;
    public int GetId()
    {
        return id;
    }
}

public class TestUsage
{
    public int IncrementId<T>() where T : Test
    {
        return 1 + T.GetId();
    }
}
Andrew O
  • 13
  • 5
  • `public int IncrementId(T item) where T : Test { return 1 + item.GetID(); }` T is a type parameter and is used to identify the type of something being used in the generic method. It's not a variable you can use to call methods on. –  Jun 04 '19 at 17:54
  • 5
    `T` is a type. `T.GetId()` is like `String.Length`: *Which* string's length do you want? There are a lot of strings out there. – 15ee8f99-57ff-4f92-890c-b56153 Jun 04 '19 at 17:57
  • `GetId` is not static, so `.GetId()` doesn't make sense. But even if you made it static, static members cannot be overridden, so you would not refer to `T.GetId()`, you would just say `Test.GetId()`. – Blorgbeard Jun 04 '19 at 18:10
  • 3
    I think you should explain what you're trying to do here. I suspect your design may be based around some misconceptions on how generics in C# work. – Blorgbeard Jun 04 '19 at 18:14

3 Answers3

1

Declaring the method as generic means that you can pass an argument of the generic type. So you could do this:

public class TestUsage
{
    public int IncrementId<T>(T test) where T : Test
    {
        return 1 + test.GetId();
    }
}

The generic type argument T doesn't mean anything unless something with that type is used either as an input argument, a return value, a variable of type T within the method, or some combination.

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
1

Since in public int IncrementId<T>(T test) the type parameter T could just be any type, C# has no clue which members this type has. You can add a generic type constraint. A way to do this, is to define an interface that types must implement to be used as type argument.

public interface IHasId
{
    int GetId();
}

class Test : IHasId
{
    public static int id = 1;
    public int GetId()
    {
        return id;
    }
}

public int IncrementId<T>(T item) where T : IHasId
{
    return item.GetId() + 1;
}

Another option is to pass a property accessor to the method

public int IncrementId<T>(T item, Func<T, int> getId)
{
    return getId(item) + 1;
}

You would call it with

int nextId = IncrementId(test, t => t.GetId());

See also:

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

You do not provide an instance of T. Try:

public int IncrementId<T>(T t) where T : Test
{
    return 1 + t.GetId();
}
Dan Byström
  • 9,067
  • 5
  • 38
  • 68