Extending templated classes for specific data types.

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

How do I extend a template class for a specific template data type? I am
trying to achieve something like....

public class SomeItem{}
public class SomeProcess < T> { }

and now the extension

public class SomeProcess<SomeItem>
{ public SomeMethod() { } // special code for just this combination }
 
Paul,

You essentially have to derive from the generic type with your specific
parameter, like so:

public class NewClass : SomeProcess<SomeItem>
{
public void SomeMethod()
{
}
}

Hope this helps.
 
Hello Nicholas

That is what I have been trying but it is causing me problems. If I have

public class NewClass : SomeProcess<SomeItem>
{
public void SomeMethod()
{
NewClass nc = new NewClass( ) ;
AddChild (nc); // routine in SomeProcess<T>
NewClass ncFirst = GetFirstChild( ) // ditto
}
}

This causes casting errors as I cannot cast from NewClass to
SomeProcess<SomeItem>.

In my office I have a brick wall with a number of impressions of my skull
and a worn circular path in the carpet.
 
Paul,

What is the signature of the AddChild method that is inherited from
SomeProcess<T>?
 
Paulustrious said:
Hello Nicholas

That is what I have been trying but it is causing me problems. If I have

public class NewClass : SomeProcess<SomeItem>
{
public void SomeMethod()
{
NewClass nc = new NewClass( ) ;
AddChild (nc); // routine in SomeProcess<T>
NewClass ncFirst = GetFirstChild( ) // ditto
}
}

This causes casting errors as I cannot cast from NewClass to
SomeProcess<SomeItem>.

In my office I have a brick wall with a number of impressions of my skull
and a worn circular path in the carpet.
If the AddChild() method has the signature AddChild(T t), it can't work,
as NewClass "is a" SomeProcess<SomeItem>, not a SomeItem.

As C# doesn't have template specialization as C++, the only way I know
is to provide a member function template (BTW, what's the C# wording for
that?)

class SomeItem { }
class SomeProcess<T>
{
void AddChild(T t) { }
public void SomeSpecialMethod<U>(U u) where U : SomeItem, T
{
AddChild(u);
}
}


HTH,
Andy
 
Nicholas,

The reality is more like this....

public class SomeProcess<T>
{
public List <SomeProcess<T> > [] Children
public string/int/class-name SomeOtherStuffNeededInClass;
public void AddChild(SomeProcess<T> childSomeProcess)
{
Children.Add(childSomeProcess) // List.Add being called.
}
}


It may look a bit odd, and I am sorry to bore you with what I am doing. I am
reading a (almost) complete database into memory including tables, keys and
foreign keys and dynamically generating in-memory copies with the foreign
keys represented by Children. The mappings are:

Database ===> MyDataSetClass : System.DataSet
Table ===> MyTable : List<MyDataRow : DataRow>
Foreign Key ==> MyKey : List< MyDataRowParentToMyDataRowChildren>

The above is not entirely correct (compile-wise or semantically) , but you
probably get the idea.
 
Thank you Andreas. You have added to the indentations in the wall. I tried
this...

class Program
{
static void Main(string [] args)
{
SomeProcess<SomeItem> ss = new SomeProcess<SomeItem>();
}
}
class SomeItem { }
class SomeProcess<T>
{
public List <SomeProcess<T>> Children = new List<SomeProcess<T>>() ;
void AddChild(SomeProcess<T> t) { Children.Add( t ); }
public void SomeSpecialMethod<U>(U u) where U :
SomeProcess<SomeItem> , T
{
Children.Add( (SomeProcess < SomeItem >) u );
}
}

But of course the Children.Add is causing the same old casting error. I can
see ways round it but only by being 'dirty'. (eg adding non-generalized
variables to my
As C# doesn't have template specialization as C++, the only way I know
is to provide a member function template (BTW, what's the C# wording for
that?)

is ...duh?
 
Paulustrious said:
Thank you Andreas. You have added to the indentations in the wall. I tried
this...

class Program
{
static void Main(string [] args)
{
SomeProcess<SomeItem> ss = new SomeProcess<SomeItem>();
}
}
class SomeItem { }
class SomeProcess<T>
{
public List <SomeProcess<T>> Children = new List<SomeProcess<T>>() ;
void AddChild(SomeProcess<T> t) { Children.Add( t ); }
public void SomeSpecialMethod<U>(U u) where U :
SomeProcess<SomeItem> , T
{
Children.Add( (SomeProcess < SomeItem >) u );
}
}

But of course the Children.Add is causing the same old casting error. I can
see ways round it but only by being 'dirty'. (eg adding non-generalized
variables to my
SomeProcess class that are specially for <U> stuff. I am new to C# so my
answer to your question...

The AddChild(SomeProcess<T> t) signature is killing my solution :-(.
Thought it was AddChild(T t).
I then see no way to do that using pure generics, as they don't have
template specialization.

However switching behavior for special circumstances can be achieved in
a "classic" way using the strategy pattern and a factory. Here is a
little sketch of what I mean:

class SomeItem { }
interface SomeSpecialMethodExec<T>
{
void SomeSpecialMethod(SomeProcess<T> item);
}
class SomeSpecialMethodExecSomeItem : SomeSpecialMethodExec<SomeItem>
{
private List<SomeProcess<SomeItem>> l;
internal SomeSpecialMethodExecSomeItem(List<SomeProcess<SomeItem>> l)
{
this.l = l;
}
void
SomeSpecialMethodExec<SomeItem>.SomeSpecialMethod(SomeProcess<SomeItem>
item)
{// special for SomeItem.
l.Add(item);
}
}
class SomeSpecialMethodExecDefault<T> : SomeSpecialMethodExec<T>
{
private List<SomeProcess<T>> l;
internal SomeSpecialMethodExecDefault(List<SomeProcess<T>> l)
{
this.l = l;
}
void SomeSpecialMethodExec<T>.SomeSpecialMethod(SomeProcess<T> item)
{// normal execution
l.Add(item);
}
}
static class SomeSpecialMethodExecFactory
{
public static SomeSpecialMethodExec<T> Create<T>
(List<SomeProcess<T>> l)
{
if(typeof(SomeItem) == typeof(T))
return (SomeSpecialMethodExec<T>)new
SomeSpecialMethodExecSomeItem((List<SomeProcess<SomeItem>>)(object)l);
return new SomeSpecialMethodExecDefault<T>(l);
}
}
class SomeProcess<T>
{
private List<SomeProcess<T>> Children = new List<SomeProcess<T>>();
private void AddChild(SomeProcess<T> t) { Children.Add(t); }
public void SomeSpecialMethod(SomeProcess<T> t)
{
// get method
SomeSpecialMethodExec<T> meth =
SomeSpecialMethodExecFactory.Create<T>(Children);
meth.SomeSpecialMethod(t);
}
}


BTW, It is usually more fun to get headache from a couple of beers that
from reorganizing some bricks ;-)

HTH,
Andy
 
Back
Top