Re: Extending objects that get returned as generics
Jon Skeet [C# MVP] <skeet@pobox.co m> wrote in
news:MPG.1e3611 621088ceff98cce c@msnews.micros oft.com:
[color=blue]
> Absolutely - if you try to add a Person to a List<Farmer>, that
> shouldn't work, should it?[/color]
Yeah I think this is another problem of the "wording" but in this case
its the actual (correct) code that is confusing. It just seems strange
that if I receive a List<T> where T: Person that I can't add a 'Person'
to it. But of course you make perfect sense in your example - if I
receive a List<Farmer> (where Farmer: Person) then of course I can't add
a Person to it because not every person is a farmer! (E I E I O).
I guess when one sees "where T: Person" they can ONLY say "T is a
Person" from OUTSIDE the function. When viewed from INSIDE the
function, T is T, and even though whatever T is may be derived from
Person, you can't treat it as a Person directly.
For example, the following compiles:
static Person mike = new Person("mike");
static Farmer john = new Farmer("john", 10);
static Farmer bob = new Farmer("bob", 20);
private static List<T> GetNames<T>() where T: Person
{
List<T> l = new List<T>();
l.Add(mike as T);
l.Add(john as T);
l.Add(bob as T);
return l;
}
private static void Test()
{
List<Person> people = GetNames<Person >();
List<Farmer> farmers = GetNames<Farmer >();
}
Both 'people' and 'farmers' will have 3 entries, but the first entry in
'farmers' is null (as expected). Furthermore, the entry that is null is
'mike', which IS a person, which is what we are specifying T should be.
Inside the function, you really do have to look at T as a macro
replacement more than simply being a Type specifier. Outside the
function, it is definitely a type specifier.
[color=blue]
> I don't know any way of expressing in C# that T must be a *base* class
> of Person, rather than *derived* from Person. I'm pretty sure it's
> possible in Java, but I'm bad at remembering the syntax there too...[/color]
I guess in this case making the parameter a List<T> doesn't make
sense... it should simply return List<Person>, or for Keith's example,
it should return a List<ADUser>. But in that case the function isn't
generic, which was the whole point, so it doesn't matter anyway.
My brain hurts now. :)
-mdb
Jon Skeet [C# MVP] <skeet@pobox.co m> wrote in
news:MPG.1e3611 621088ceff98cce c@msnews.micros oft.com:
[color=blue]
> Absolutely - if you try to add a Person to a List<Farmer>, that
> shouldn't work, should it?[/color]
Yeah I think this is another problem of the "wording" but in this case
its the actual (correct) code that is confusing. It just seems strange
that if I receive a List<T> where T: Person that I can't add a 'Person'
to it. But of course you make perfect sense in your example - if I
receive a List<Farmer> (where Farmer: Person) then of course I can't add
a Person to it because not every person is a farmer! (E I E I O).
I guess when one sees "where T: Person" they can ONLY say "T is a
Person" from OUTSIDE the function. When viewed from INSIDE the
function, T is T, and even though whatever T is may be derived from
Person, you can't treat it as a Person directly.
For example, the following compiles:
static Person mike = new Person("mike");
static Farmer john = new Farmer("john", 10);
static Farmer bob = new Farmer("bob", 20);
private static List<T> GetNames<T>() where T: Person
{
List<T> l = new List<T>();
l.Add(mike as T);
l.Add(john as T);
l.Add(bob as T);
return l;
}
private static void Test()
{
List<Person> people = GetNames<Person >();
List<Farmer> farmers = GetNames<Farmer >();
}
Both 'people' and 'farmers' will have 3 entries, but the first entry in
'farmers' is null (as expected). Furthermore, the entry that is null is
'mike', which IS a person, which is what we are specifying T should be.
Inside the function, you really do have to look at T as a macro
replacement more than simply being a Type specifier. Outside the
function, it is definitely a type specifier.
[color=blue]
> I don't know any way of expressing in C# that T must be a *base* class
> of Person, rather than *derived* from Person. I'm pretty sure it's
> possible in Java, but I'm bad at remembering the syntax there too...[/color]
I guess in this case making the parameter a List<T> doesn't make
sense... it should simply return List<Person>, or for Keith's example,
it should return a List<ADUser>. But in that case the function isn't
generic, which was the whole point, so it doesn't matter anyway.
My brain hurts now. :)
-mdb
Comment