You can apply a constraint and do it like this (With a little linq, your method will look like this):
public interface IHasId
{
int Id { get; }
}
public class Foo<T> where T : IHasId
{
private List<T> children;
public IHasId GetById(int id)
{
return this.children.FirstOrDefault(x => x.Id == id);
}
}
UPDATE
I am leaving my answer above as is because that clearly answers the OPs question and whomever is downvoting does not understand generics.
@Enigmativity commented in his answer to one of my comments:
No, you're not answering the question. The OP wants the method constrained - and not the entire class. He wants T to be any type.
If the OP wants the method constrained only and not the entire class, then the answer is as below:
Constraint Method Only
You cannot apply a constraint to the method only because when your class is constructed, the generic has to be closed. In other words, you are storing type T
(s) in the children
field, type T
will have to be closed at the class level. Thus, type T
has to be constrained at the class level.
If you want the method to be generic only then you cannot use the type T
at the class level. Your class does not have to be generic to have a generic method. You can still have a generic method in your class as I have shown below:
public class Foo
{
// The children list is not of type T, but it has been closed with
// type SomeClass
private List<SomeClass> children;
// Here we are saying this method will work so long as it is called with
// any T that implements IHasId
// The class is not generic, but the method is
public bool IsIdOver100<T>(T hasId) where T : IHasId
{
return hasId.Id > 100;
}
}
public class SomeClass : IHasId
{
public int Id { get { /*...code*/ } }
}
FYI, @engimativity's answer is also applying the constraint at the class level but indicating to use inheritance. That will still apply the constraint at the class level and the inheritance makes no difference.
@kblok also made a similar comment in the comments to this answer:
he's asking how to apply a constraint in a method, you're not answering the question
And this is the solution, kblok is proposing:
public TItem GetById<TItem>(int id)
where TItem : T, IHasId
{
return children.Select(t => t is TItem).Cast<TItem>().FirstOrDefault(t => t.Id == id);
}
There are two issues with the above: 1. The method is casting so it is not generic. 2. The constraint is saying TItem : T
which makes no sense since T
is not a closed type and there are no constraints placed on what T
can be. I am not even sure why the compiler would even allow that but there may be a good reason for it. If T
had a constraint at the class level such as where T : IAnotherInterface
, then it will make sense to place a constraint at the method level which says: where TItem : T, IHasId
but that still leaves the method non-generic if there is casting going on.
Some More Info for OP
If you want to inherit the Foo
class, you can still do that with or without closing it. Here is example with closing it:
public class FooOfSomeClass : Foo<SomeClass>
{
// you can have addition methods, properties stuff here like any other inheriting class
}