How to use this generic?

  • Thread starter Thread starter Brett Romero
  • Start date Start date
B

Brett Romero

I have this class:

public class MyClass<TValue> where TValue : IMyClass, new( )
{...}

I need to create a class that will hold instances of the above class
using List<>:

public class MyClassCollection : List<View<TValue>>
{...}

The above will give this error:

The type or namespace name 'TValue' could not be found (are you missing
a using directive or an assembly reference?)

How can I do this?

Thanks,
Brett
 
Brett,

If you do not specify TValue in the class declaration, then it assumes
that TValue is the name of the type, and not a type parameter. You want to
do:

public class MyClassCollection<TValue> : List<View<TValue>>
{}

Hope this helps.
 
Nicholas said:
Brett,

If you do not specify TValue in the class declaration, then it assumes
that TValue is the name of the type, and not a type parameter. You want to
do:

public class MyClassCollection<TValue> : List<View<TValue>>
{}

Hope this helps.

The problem with doing it that way means the collection will only hold
one type of MyClass. Let's say i do this:

MyClass<green> green = new MyClass<green>();
MyClass<red> red = new MyClass<red>();
MyClass<orange> orange = new MyClass<orange>();

Now I want to add each of them to the MyClassCollection. Using your
technique, it looks like this:

MyClassCollection<green> ColorCollection = new
MyClassCollection<green>();

I can't do MyClassCollection.Add(red) because it only takes types of
green. I want this collection to hold all three colors.

Thanks,
Brett
 
Brett,

Then you need to find a base class/interface that they all share, and
work with the lowest common denominator.

So say Green, Red, and Orange derive from Color. Your class would look
like:

public class MyClassCollection : List<View<Color>>
{}

And then you would have to cast to Red, Green and Orange for the
specific type functionality.
 
Nicholas said:
Brett,

Then you need to find a base class/interface that they all share, and
work with the lowest common denominator.

So say Green, Red, and Orange derive from Color. Your class would look
like:

public class MyClassCollection : List<View<Color>>
{}

And then you would have to cast to Red, Green and Orange for the
specific type functionality.

Yes and I have an interface that does that. Say Color (from above) is
the interface name. I get this compile time error:

The type 'Color' must have a public parameterless constructor in order
to use it as parameter 'TValue' in the generic type or method
'MyClass<TValue>'

Is it possible to use only the interface (vs. base class) this way?

Thanks,
Brett
 
"Brett Romero" <[email protected]> a écrit dans le message de (e-mail address removed)...

|I have this class:
|
| public class MyClass<TValue> where TValue : IMyClass, new( )
| {...}
|
| I need to create a class that will hold instances of the above class
| using List<>:
|
| public class MyClassCollection : List<View<TValue>>
| {...}
|
| The above will give this error:
|
| The type or namespace name 'TValue' could not be found (are you missing
| a using directive or an assembly reference?)

As Nicholas said, you need to declare the type TValue before using it.

I have a question...

1. why are you deriving from a generic class, are you planning on extending
List<T> functionality ?

....and a suggestion ...

start out by declaring a non-generic class from which you will derive your
generic class, then you can have a list of the base class that will hold
different bound types.

public class MyClass
{
// non-generic stuff
}

public class MyClass<valueT> : MyClass
{
// generic stuff
}

then simply use a List<MyClass> as it is without deriving.

Of course, you will have to query each item to find its type and then cast
it to the appropriate type to use it.

Joanna
 
I have a question...

1. why are you deriving from a generic class, are you planning on extending
List<T> functionality ?

I'm not extending List<> functionality. What gives you that idea? I
simply want a typed list. I could choose to declare the List<> as
private in the class instead of inheriting it. Either way, I need it
typed.

Brett
 
"Brett Romero" <[email protected]> a écrit dans le message de (e-mail address removed)...

| I'm not extending List<> functionality. What gives you that idea? I
| simply want a typed list. I could choose to declare the List<> as
| private in the class instead of inheriting it. Either way, I need it
| typed.

By binding a List<T> to a given type, you are creating a "typed list".
Genreic lists are strongly typed as soon as they are bound.

List<Customer> customerList = new List<Customer>();

now customerList is a typesafe list that can only accept and return
Customers.

You don't need to derive from it or do anything else.

Joanna
 
Joanna said:
"Brett Romero" <[email protected]> a écrit dans le message de (e-mail address removed)...

| I'm not extending List<> functionality. What gives you that idea? I
| simply want a typed list. I could choose to declare the List<> as
| private in the class instead of inheriting it. Either way, I need it
| typed.

By binding a List<T> to a given type, you are creating a "typed list".
Genreic lists are strongly typed as soon as they are bound.

List<Customer> customerList = new List<Customer>();

now customerList is a typesafe list that can only accept and return
Customers.

You don't need to derive from it or do anything else.

Let me clarify a little more. I want to call MyClass.Add() vs
MyClass.List.Add(). If I don't inherit, the List's Add, Remove, Count,
etc need to be encapsulated. This means I to have create all of those
methods. Inheritance avoids that.

Brett
 
Brett Romero said:
Let me clarify a little more. I want to call MyClass.Add() vs
MyClass.List.Add(). If I don't inherit, the List's Add, Remove, Count,
etc need to be encapsulated. This means I to have create all of those
methods. Inheritance avoids that.

At the expense of making people think that you're trying to specialise
the behaviour of lists - because that's what inheritance is for.

See http://msmvps.com/jon.skeet/archive/2006/03/04/inheritancetax.aspx
for my view on the risks and overuse of inheritance.
 
"Brett Romero" <[email protected]> a écrit dans le message de (e-mail address removed)...

Let me clarify a little more. I want to call MyClass.Add() vs
MyClass.List.Add(). If I don't inherit, the List's Add, Remove, Count,
etc need to be encapsulated. This means I to have create all of those
methods. Inheritance avoids that.

As Jon says, you are really overusing inheritance here.

Assuming you want to include an internal list in a class, then you don't
want to go to the expense of inheriting a generic list just to include the
derived class, which is identical in behaviour to the class from which it
derives.

I take it you want something like this

publlic class Employee
{
...
}

public class Company
{
private string name;

private Address address;

...

private List<Employee> employees = new List<Employee>();

// public properties, etc
}

This then means that you would call :

{
aCompany.Employees.Add(...)
}

Which makes more sense than deriving Company from List<Employee>, as a
Company could also have other lists of things like Customers, etc.

This way of allowing access to the list itself, is known as Aggregation and
it assumes that the list of objects is not "owned" by the containing object.
IOW, the people that we can call Employees are not created by the Company,
they have a life outside of the Company.

OTOH, if you want to model something like a SalesOrder, then you would
encapsulate the list, hiding its own methods, thus preventing unauthorised
use of the list.

public class ReadOnlyList<T> : IEnumerable<T>
{
public T this[int index] { get {...} }

public int Count { get {...} }

IEnumerator<T> IEnumerable<T>.GetEnumerator() { get {...} }

private List<T> list;

public ReadOnlyList(List<T> list)
{
this.list = list;
}
}

This is a readonly list wrapper class that allows examination of the items
in a list but not manipulation of the list itself. It is a wrapper class.

public class SalesOrder
{
public class Line
{
...

internal Line() // only accessible in business class assembly
{
...
}
}

private List<Line> lines = new List<Line>();

public ReadOnlyList<Line> Lines
{
get { return new ReadOnlyList<Line>(lines); }
}

public Line AddLine()
{
Line result = new Line();
lines.Add(result);
return result;
}
}

Now the Lines property returns a read-only list for examination and
alteration of the items only.

Adding a Line is only possible by asking the SalesOrder to create one and
then return it for editing.

This way of preventing list operations whilst allowing operations on the
items, is known as Composition.

Does that help or confuse ? :-)

Joanna
 
[...]

To add to what the others wrote:

List<T> isn't really meant for inheritance. Most of its methods are
static, and so can't be overridden and still work polymorphically as a
List<T>.

Collection<T> is a much better bet if you want to descend from a
collection class and still have strong typing.

-- Barry
 
The thread is veering off the point. We're getting distracted about
why List<T> shouldn't be inherited in this case. I agree it shouldn't.
I burn the base class fairly quick for little gain. That aside...

Now, this still doesn't get me anywhere with the original problem.
Which is, How do I handle List<MyClass<TValue>> in the collection
class?

Thanks,
Brett
 
To reiterate, I'd like to do something like this:

MyClass<green> green = new MyClass<green>();
MyClass<red> red = new MyClass<red>();
MyClass<orange> orange = new MyClass<orange>();

MyClassCollection myColl = new MyClassCollection();
myColl.Add( green );
myColl.Add( red );
MyColl.Add( orange );

MyClass, MyClassCollection and all of the specific color classes (i.e.
green, red, orange) implement IMyClass. Isn't there a way for me to
exploit this so I can get that common type into the collection's
List<MyClass<IMyClass>> (or how ever it should be)?

Brett
 
"Brett Romero" <[email protected]> a écrit dans le message de (e-mail address removed)...

| To reiterate, I'd like to do something like this:
|
| MyClass<green> green = new MyClass<green>();
| MyClass<red> red = new MyClass<red>();
| MyClass<orange> orange = new MyClass<orange>();
|
| MyClassCollection myColl = new MyClassCollection();
| myColl.Add( green );
| myColl.Add( red );
| MyColl.Add( orange );
|
| MyClass, MyClassCollection and all of the specific color classes (i.e.
| green, red, orange) implement IMyClass. Isn't there a way for me to
| exploit this so I can get that common type into the collection's
| List<MyClass<IMyClass>> (or how ever it should be)?

Why would MyClassCollection implement IMyClass ???

What do you mean: all your specific color classes implement IMyClass, why
would they do that ???

As long as MyClass<T> implements the non-generic IMyClass interface, then
you can simply use List<IMyClass> to hold instances of any bound MyClass<T>
type.

public interface IMyClass
{
...
}

public class Green
{
...
}

public class Red
{
...
}

public class Orange
{
...
}

public class MyClass<T> : IMyClass
{
...
}

public class MyClassCollection : List<IMyClass>
{
...
}

Joanna
 
I have this doing what I need but the approach turned out to be very
different.

Thanks for the input,
Brett
 

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

Back
Top