Generics questions in .NET 2.0

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

Guest

Make a template of a template:

public class A<T>
{
A(string s){}
}


public class D<Tobject, Tclass> :
where Tobject : Object
where Tclass : A<Tclass>
{
public Tobject someFunction()
{
Tclass c = new Tclass("Test"); // Compiler error: Tclass doesn't have new
constraint
return null; // Compiler error: Tobject is not nullable
}
}

How do I let the compiler know that Tobject is nullable?
How do I let it know that since Tclass is constrained to types of A it must
implement the new operator with string argument?
 
instead of
where Tobject : Object

use
where Tobject : Nullable<>

haven't tried but an idea..
 
Dave,

You won't be able to do this the way you want. There are a number of
things that need to be changed here.

First, your declarations should look like this:


public class A<T>
{
public void Initialize(string s){}
}

public class D<TObject, TClass>
where TObject : class
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return null;
}
}

When you use "class" as a constraint, it means that you can only pass in
reference types. This is what allows null to be returned for TObject. The
second thing is you have to declare your initialization outsize of the
constructor. The reason for this is that the new constraint only constrains
on parameterless constructors. Because of this, you need a separate method
to call on A which can perform the necessary setup.

Hope this helps.
 
Re the new(string) signature, you can't do this at design time (yet - maybe
this will get more powerful in 3.0?). One option is to use reflection to
test this in a static ctor (I posted an example of this a week-or-so ago) -
you'd also need to use the reflected ctor to create your object, so you
could perhaps persist this in a private static field; the validation will
only happen at runtime, but at least it will happen as early as possible.

The Tobject : Object doesn't look like it will do much, since everything is
derived from Object

When you say nullable, do you need to be able to handle Nullable<T>? or just
classes (reference types). If the latter, you could replace this line with
Tobject : class; this then compiles.

Hope this helps,

Marc
 
Hi,

See inline

Dave said:
Make a template of a template:

public class A<T>
{
A(string s){}
}


public class D<Tobject, Tclass> :
where Tobject : Object
where Tclass : A<Tclass>
{
public Tobject someFunction()
{
Tclass c = new Tclass("Test"); // Compiler error: Tclass doesn't have new
constraint
return null; // Compiler error: Tobject is not nullable
}
}

How do I let the compiler know that Tobject is nullable?
The Tobject : object constraint doesn't do anything at all, because
everything in the .NET world derives (or can be boxed in order to
derive) from an object. The right constraint to specify a reference type
would beTobjkec
 
Thank you, that was very helpful.

So just to confirm: in C# 2.0 is there no way to define a generic class so
that the template type can be instantiated inside the class, unless the
template type is explicitly constrained to "new()" AND the template type must
define a parameterless constructor?

Nicholas Paldino said:
Dave,

You won't be able to do this the way you want. There are a number of
things that need to be changed here.

First, your declarations should look like this:


public class A<T>
{
public void Initialize(string s){}
}

public class D<TObject, TClass>
where TObject : class
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return null;
}
}

When you use "class" as a constraint, it means that you can only pass in
reference types. This is what allows null to be returned for TObject. The
second thing is you have to declare your initialization outsize of the
constructor. The reason for this is that the new constraint only constrains
on parameterless constructors. Because of this, you need a separate method
to call on A which can perform the necessary setup.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Dave Booker said:
Make a template of a template:

public class A<T>
{
A(string s){}
}


public class D<Tobject, Tclass> :
where Tobject : Object
where Tclass : A<Tclass>
{
public Tobject someFunction()
{
Tclass c = new Tclass("Test"); // Compiler error: Tclass doesn't have new
constraint
return null; // Compiler error: Tobject is not nullable
}
}

How do I let the compiler know that Tobject is nullable?
How do I let it know that since Tclass is constrained to types of A it
must
implement the new operator with string argument?
 
Yep.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Dave Booker said:
Thank you, that was very helpful.

So just to confirm: in C# 2.0 is there no way to define a generic class so
that the template type can be instantiated inside the class, unless the
template type is explicitly constrained to "new()" AND the template type
must
define a parameterless constructor?

Nicholas Paldino said:
Dave,

You won't be able to do this the way you want. There are a number of
things that need to be changed here.

First, your declarations should look like this:


public class A<T>
{
public void Initialize(string s){}
}

public class D<TObject, TClass>
where TObject : class
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return null;
}
}

When you use "class" as a constraint, it means that you can only pass
in
reference types. This is what allows null to be returned for TObject.
The
second thing is you have to declare your initialization outsize of the
constructor. The reason for this is that the new constraint only
constrains
on parameterless constructors. Because of this, you need a separate
method
to call on A which can perform the necessary setup.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Dave Booker said:
Make a template of a template:

public class A<T>
{
A(string s){}
}


public class D<Tobject, Tclass> :
where Tobject : Object
where Tclass : A<Tclass>
{
public Tobject someFunction()
{
Tclass c = new Tclass("Test"); // Compiler error: Tclass doesn't have
new
constraint
return null; // Compiler error: Tobject is not nullable
}
}

How do I let the compiler know that Tobject is nullable?
How do I let it know that since Tclass is constrained to types of A it
must
implement the new operator with string argument?
 
Well, I spoke too soon. You could get the type of T, and then get the
constructor and call that through reflection. This assumes you know what
the parameter list of the constructor will be, however.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Dave Booker said:
Thank you, that was very helpful.

So just to confirm: in C# 2.0 is there no way to define a generic class so
that the template type can be instantiated inside the class, unless the
template type is explicitly constrained to "new()" AND the template type
must
define a parameterless constructor?

Nicholas Paldino said:
Dave,

You won't be able to do this the way you want. There are a number of
things that need to be changed here.

First, your declarations should look like this:


public class A<T>
{
public void Initialize(string s){}
}

public class D<TObject, TClass>
where TObject : class
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return null;
}
}

When you use "class" as a constraint, it means that you can only pass
in
reference types. This is what allows null to be returned for TObject.
The
second thing is you have to declare your initialization outsize of the
constructor. The reason for this is that the new constraint only
constrains
on parameterless constructors. Because of this, you need a separate
method
to call on A which can perform the necessary setup.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Dave Booker said:
Make a template of a template:

public class A<T>
{
A(string s){}
}


public class D<Tobject, Tclass> :
where Tobject : Object
where Tclass : A<Tclass>
{
public Tobject someFunction()
{
Tclass c = new Tclass("Test"); // Compiler error: Tclass doesn't have
new
constraint
return null; // Compiler error: Tobject is not nullable
}
}

How do I let the compiler know that Tobject is nullable?
How do I let it know that since Tclass is constrained to types of A it
must
implement the new operator with string argument?
 
Nicholas said:
Dave,

You won't be able to do this the way you want. There are a number of
things that need to be changed here.

First, your declarations should look like this:


public class A<T>
{
public void Initialize(string s){}
}

public class D<TObject, TClass>
where TObject : class
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return null;
}
}
just to round it up, Tobject can be a value type, too:
public class D<TObject, TClass>
where TClass : A<TClass>, new()
{
public TObject someFunction()
{
TClass c = new TClass();
c.Initialize("Test");
return default(TObject);
}
}
 

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