Different generic type parameter in generic class constructorparameter

T

tadmill

Is it possible to pass a generic parameter of the same class to to its
constructor, where the "T" type passed in the constructor is different
than the "T" type of the instanced class?

ie,

public class SomeList<T>
{

public SomeList(SomeList<T> thisSomeList)
{
//another SomeList<T> where the T is different type
}
}

This may reveal my relatively new understanding of class generics, but
I didn't find a similar post.

TIA
Terry
 
J

Jon Skeet [C# MVP]

Is it possible to pass a generic parameter of the same class to to its
constructor, where the "T" type passed in the constructor is different
than the "T" type of the instanced class?

No, and you can't write generic constructors either. However, you *can*
write a generic static method to return the new list:

public class SomeList<T>
{
public static SomeList<T> CreateList<V> (SomeList<V> otherList)
{
...
}
}
 
M

Marc Gravell

Which of course begs the question...
why aren't generic constructors allowed?

Well, the calling syntax alone would be interesting... you'd need:

new SomeClass<TClassArg1 , ... , TClassArgN><TCtorArg1 , ... ,
TCtorArgN>
And it would preclude both " : new()" (constraint-based) and
Activator.CreateInstance() etc.
I suspect that it might help to see a sensible use-case where it can't
already be solved (as Jon said) with a static generic Create<...>
method; (genuine question) can you think of any such examples?

Marc
 
J

Jon Skeet [C# MVP]

Marc Gravell said:
Well, the calling syntax alone would be interesting... you'd need:

new SomeClass<TClassArg1 , ... , TClassArgN><TCtorArg1 , ... ,
TCtorArgN>
And it would preclude both " : new()" (constraint-based) and
Activator.CreateInstance() etc.
I suspect that it might help to see a sensible use-case where it can't
already be solved (as Jon said) with a static generic Create<...>
method; (genuine question) can you think of any such examples?

Chaining a constructor call from a derived class to a base class would
present a problem. Just occasionally I've found this a nuisance, but
not enough to make me feel that its omission was a mistake.
 
T

tadmill

No, and you can't write generic constructors either. However, you *can*
write a generic static method to return the new list:

public class SomeList<T>
{
    public static SomeList<T> CreateList<V> (SomeList<V> otherList)
    {
         ...
    }

}

--
Jon Skeet - <[email protected]>
Web site:http://www.pobox.com/~skeet 
Blog:http://www.msmvps.com/jon.skeet
C# in Depth:http://csharpindepth.com

Thanks for the suggestion; that static function I think will work
nicely in what I'm trying to do, which is mapping class properties to
a table definition, and then create a collection of that class with
the table data.

Where a generic constructor could be useful is recursion; in my
situation, it would have been nice to recursively create generic list
objects, where one of the classes has a SomeList<T> property of it's
own.

And this generic constructor would have been a 2nd overloaded method.
What if the compiler were to allow generic constructors, given that a
default ctor was explicitly defined, and a restriction on how many
generic type parameters could be used? That could allow recursion.

Thanks again for the help,
Terry
 
T

tadmill

No, and you can't write generic constructors either. However, you *can*
write a generic static method to return the new list:

public class SomeList<T>
{
    public static SomeList<T> CreateList<V> (SomeList<V> otherList)
    {
         ...
    }

}

--
Jon Skeet - <[email protected]>
Web site:http://www.pobox.com/~skeet 
Blog:http://www.msmvps.com/jon.skeet
C# in Depth:http://csharpindepth.com

Thanks for the suggestion; that static function I think will work
nicely in what I'm trying to do, which is mapping class properties to
a table definition, and then create a collection of that class with
the table data.

Where a generic constructor would have been nice, would have been to
recursively create generic list
objects, where one of the classes has a SomeList<T> property of it's
own, although I hadn't gotten that far.

But this generic constructor would have been a 2nd overloaded method.
What if the compiler were to allow generic constructors, given that a
default ctor was explicitly defined, and a restriction on how many
generic type parameters could be used? That could allow recursion
with different types.

Thanks again for the help,
Terry
 
P

Pavel Minaev

Well, the calling syntax alone would be interesting... you'd need:

new SomeClass<TClassArg1 , ... , TClassArgN><TCtorArg1 , ... ,
TCtorArgN>

Not really; they could just introduce the same restriction that C++
constructor templates have - that types of all arguments in the call
must be deducible and cannot be specified explicitly.
And it would preclude both " : new()" (constraint-based) and
Activator.CreateInstance() etc.
Why?

I suspect that it might help to see a sensible use-case where it can't
already be solved (as Jon said) with a static generic Create<...>
method; (genuine question) can you think of any such examples?

It is a standard .NET pattern for a collection to have a constructor
taking an enumerable. The desire to further extend it to allow passing
collections of compatible item types only makes sense. Yes, it can be
done with a factory method, but a better question is, why workaround
when the language could provide a more straightforward way to handle
this without any downsides?
 
M

Marc Gravell

Why?
OK, I guess that in *some* cases the overloaded form of
Activator.CreateInstance could try to do some inference, but there are
big problems when there is no preferred form - but this isn't anything
new... so fair enough ;-p
It is a standard .NET pattern for a collection to have a constructor
taking an enumerable.
When that enumerable is a different type, another option would be to
translate the tye *before* passing it to the ctor; with LINQ this is a
single call to the Cast or OfType extension methods. This doesn't
necessitate another factory method, so seems quite appealling - and it
would be trivial to reproduce in .NET 2.0 (via an iterator block) if
needed - or indeed, the ConvertAll method if using List<T> [both shown
below].

Marc

using System.Collections.Generic;
using System.Linq;
class A { }
class B : A { }
static class Program
{
static void Main()
{
List<B> bList = new List<B> { new B(), new B(), new B() };

List<A> aList1 = bList.ConvertAll(b => (A)b);
List<A> aList2 = new List<A>(bList.Cast<A>());
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top