Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constraints on Generics ??

0 views
Skip to first unread message

andrew queisser

unread,
Oct 7, 2003, 11:10:28 AM10/7/03
to
I've read some material on the upcoming Generics for C#. I've
seen two types of syntax used for constraints:
- direct specification of the interface in the angle brackets
- where clauses

I looked at the files in the Gyro download but I couldn't find any
mention of constraints. Can anyone enlighten me what the current
status is and what we can expect when Generics are released?

Thanks,
Andrew Queisser


Jay B. Harlow [MVP - Outlook]

unread,
Oct 7, 2003, 11:27:52 AM10/7/03
to
Andrew,
The following articles discuss Generics & Constraints.

http://msdn.microsoft.com/msdnmag/issues/03/09/NET/default.aspx

http://msdn.microsoft.com/msdnmag/issues/03/10/NET/default.aspx

Hope this helps
Jay

"andrew queisser" <andrew....@hp.com> wrote in message
news:3f82d8d7$1...@usenet01.boi.hp.com...

Eric Gunnerson [MS]

unread,
Oct 7, 2003, 6:28:33 PM10/7/03
to
We'll have some new information on the constraints syntax - and the other
language features - on the MSDN C# developer center in the next few weeks.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://blogs.gotdotnet.com/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.
"Jay B. Harlow [MVP - Outlook]" <Jay_H...@email.msn.com> wrote in message
news:ehXSWeOj...@TK2MSFTNGP11.phx.gbl...

Jay B. Harlow [MVP - Outlook]

unread,
Oct 7, 2003, 6:41:54 PM10/7/03
to
Eric,
What about the VB.NET syntax (sly evil grin).

Jay

"Eric Gunnerson [MS]" <eri...@online.microsoft.com> wrote in message
news:%23$bkYJSjD...@TK2MSFTNGP09.phx.gbl...

Matthew W. Jackson

unread,
Oct 8, 2003, 2:17:20 AM10/8/03
to
I'm personally wondering if an interface will be added to the built-in
numeric types for math operations. That way a Generic class could require a
template parameter to be INumeric (or something similar) and call the Add,
Subtract, Multiply, or Divide method. I think that maybe a Zero and One
property on the interface might be nice, as well, although IConvertible
might technically cover the need for that.

It certainly would be nice for such an interface to be added to Int32,
Single, Decimal, and similar structures.
If not, I have a solution to the problem that uses an outside class to
perform the operations, but it's not nearly as elegant.

Maybe I'm just getting ahead of myself here.

"Jay B. Harlow [MVP - Outlook]" <Jay_H...@email.msn.com> wrote in message

news:%23PML6QS...@TK2MSFTNGP12.phx.gbl...

Dietmar Kuehl

unread,
Oct 8, 2003, 5:13:27 AM10/8/03
to
"Eric Gunnerson [MS]" <eri...@online.microsoft.com> wrote:
> We'll have some new information on the constraints syntax - and the other
> language features - on the MSDN C# developer center in the next few weeks.

This seems to indicate that the generics extension to C# and the .Net
framework is not yet cast into stone. Good! From all information on C#
generics I have seen so far it seems to lack essential features for
effective generic programming, most notable the ability to infer associated
types from type arguments.

Essentially, I'm strongly interested in implementing algorithms independent
from the underlying data structure. This is essentially the core of C++'s
STL: algorithms are not bound to a particular data structure but instead
operate on auxiliary entities which form an abstraction of the algorithm's
needs. For example, the STL algorithms operate on iterators.

To be more concrete, say I want to implement a simple algorithm determining
the position of the minimum value in a multi-pass sequence. A C++ algorithm
for this would look something like this:

template <typename ForwardIterator>
ForwardIterator
min_element(ForwardIterator begin, ForwardIterator end)
{
ForwardIterator rc = begin;
if (begin != end)
while (++begin != end)
if (*begin < *rc)
rc = begin;
return rc;
}

Now, the C# approach to some aspects of this function is somewhat different
but essentially the same functionality could be reasonable, too. Instead of
using an iterator, probably an enumerator would be used and the less than
operator would be replaced by call to 'comareTo()' of an comparer interface:

public interface Enumerator<T> {
public T next();
// probably some more functions
}

public interface Comparer<T> {
public bool compareTo(T other);
}

public class algos {
public static E MinElement<E, C>(E enumerator, C comparer)
where E: Enumerator<T> // or: E: Enumerator<E.ValueType>
where C: Comparer<T> // ... C: Comparer<E.ValueType>
{
// whatever...
}
}

The tricky part is the [reasonable] need to specify the details of the
type arguments in the constraints: although the sequence' element type 'T'
is implicit in 'E' and 'C', it has to be accessible in the constraints,
too - well, that is, in the form given above, it is actually infered rather
than given. Of course, there are other alternatives like allowing class
level aliases as is indicated by the comments but being able to infer
associated types via the constraints seems more consistent.

I also considered using the corresponding interfaces directly, ie.
something like this:

...
public static Enumerator<T> MinElement<T>(Enumerator<T> enumerator,
Comparer<T> comparer)
...

but this doesn't really scale: for algorithms a little bit more complex
there are typically multiple types associated with just a singleargument
to the function. While it is reasonable for these arguments to support
multiple interfaces, it doesn't seem feasible to fold all those types
into just one interface. Also, the argument types would tend to be rather
specific to a particular algorithm which is clearly not the goal. The
requirements imposed by the constraints to implement certain interfaces is
already bad enough with fairly general interfaces.

This is clearly the most important feature which seems to be absent (at
least from the public documentation I have seen; I can't install Gyro
and check there because I'm a professional software developer and not a
researcher while the license effectively seems to exclude the former).

The other feature I would like to see although I think it is possible to
emulate it to some degree is [partial] specialization: Given a generic
algorithm, provide a specialized implementation for a more specific case.
For functions this can be mostly implemented using overloading possibly
combined with some form of tagging scheme. However, spezializing the
generic implementation makes the intent clearer and there is no good
alternative approach for generic classes (maybe it is doable using some
form of delegation together with corresponding overloading but this does
not seem to be particularily maintainable.
--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

Dietmar Kuehl

unread,
Oct 8, 2003, 7:14:12 AM10/8/03
to
"Matthew W. Jackson" <the...@hotmail.com> wrote:
> I'm personally wondering if an interface will be added to the built-in
> numeric types for math operations. That way a Generic class could require a
> template parameter to be INumeric (or something similar) and call the Add,
> Subtract, Multiply, or Divide method. I think that maybe a Zero and One
> property on the interface might be nice, as well, although IConvertible
> might technically cover the need for that.

Two notes:

- For this to work smoothly, 'INumeric' or whatever it is called would, of
course, needs to be a generic interface: eg. the 'Multiply' function for
type 'T' would [normally] return a 'T', too. Normally: well, multiplying
two imaginary numbers (ie. the orthogonal to real numbers: a complex
number with a zero real part) yields a real number. The associated types
issue I mentioned in another article in an even more interesting setting.

- It seems to look attractive to get some form of retrofitting interfaces
to existing types you cannot change: without this capability, you would
not be able to use them with generic implementations applying constraints.
Built-in types are just one example. Third party libraries are another
one.

Matthew W. Jackson

unread,
Oct 8, 2003, 8:40:58 AM10/8/03
to
Well, my alternative is to use an outside class, which would allow
retrofitting to any type. I'm just not sure if its possible, and like I
said it isn't nearly as elegent. It would have to implement something like
IMathOperations<T>.

This would require it to be possible to have a restraint on one type
parameter that is dependant on another. The Generic class that needed to do
operations would take one parameter, N, that could be of any type, and
another parameter, lets say O, that would have to be of IMathOperations<N>.
If this is possible, then I will have no problem performing mathematical
operations in generic classes and methods. Otherwise, this would have to be
done with boxing/unboxing, which would somewhat defeat the purpose (although
not entirely).

But I figure if the .NET Framework added INumeric (or INumeric<T>, as you
said), it wouldn't take long for third party libraries to use it everywhere.
I know old libraries wouldn't have it, but the framework is still young, and
most libraries still have a chance at new versions being released. Besides,
one could get around this by making their own similar structure to hold the
data that implements the interface and had an implicit or explicit cast
operator from the library's type, and use it semi-transparently with the
generic methods (hackish, I know). I'm just saying it would be nice for
this to at least be on the core framework's numeric types. I'm assuming
that a type like Int32 would be able to implement INumeric<Int32> without
breaking any compatibility with older libraries. It would probably be best
for it to be done with explicit interface implementation anyway, as an
.AddTo(int) method (and all the others) would certainly clutter up the
class. And I know where there are some cases where T * T is not of type T,
but most of the time you want to restrict the math to those cases. You
can't do an aggregate sum easily if that's not the case, unless you have a
completely dynamic type system. I think in C# that many operations on Byte
yield a non-Byte, but I would still expect any generic function to keep the
result as a Byte...otherwise I'd convert the data first.

My head is really still spinning with the idea of generics in C#. I really
like C# as it is now, and the fact that its getting something as great as
generics is wonderful. The new iterator construct looks promising as well,
as it would greatly simplify coding, say, an enumerator for a binary tree (I
have one in my Red Black Tree implementation, but I know its horribly
inefficient). I have other possible uses for the new iterators, but I until
the exact syntax/usage/restrictions are hammered out, I don't want to think
about it too much.

"Dietmar Kuehl" <dietma...@yahoo.com> wrote in message
news:5b15f8fd.03100...@posting.google.com...

andrew queisser

unread,
Oct 8, 2003, 12:13:36 PM10/8/03
to
"Dietmar Kuehl" <dietma...@yahoo.com> wrote in message
news:5b15f8fd.03100...@posting.google.com...
> ...

> While it is reasonable for these arguments to support
> multiple interfaces, it doesn't seem feasible to fold all those types
> into just one interface. Also, the argument types would tend to be rather
> specific to a particular algorithm which is clearly not the goal. The
> requirements imposed by the constraints to implement certain interfaces is
> already bad enough with fairly general interfaces.
> ...

I'm still trying to understand exactly what you're saying but it seems to
boil down to the problem that unlike C# generics C++ templates
a) work strictly with implicit requirements for the type parameters and
b) associated types can be inferred by the compiler

I'm not sure whether you're saying that your C# version of MinElement
would work or not. If MinElement would work, can you supply a simple
example of a STL-like algorithm that wouldn't work?

Thanks,
Andrew


Dietmar Kuehl

unread,
Oct 8, 2003, 4:49:45 PM10/8/03
to
andrew queisser wrote:
> I'm still trying to understand exactly what you're saying but it seems to
> boil down to the problem that unlike C# generics C++ templates
> a) work strictly with implicit requirements for the type parameters and

Well, yes, they do but I don't mind a more explicit approach. In fact,
I'm pretty sure that the implicit approach causes loads of problems
although it might make hacking up simple templates easier. I think,
the constraints in C# are a reasonable approach in general although
I also think that the current specification is not up to what I want.

> b) associated types can be inferred by the compiler

This is the aspect I'm really interested in: it is absolutely necessary
for any non-trivial generic stuff to infer associated types. Without
this ability, generics or templates are nearly useless. Explicit
requirements make things even worse: in the example I gave, I only
referred to the inferred type 'T' within the constraints. There, however,
it is essential that the type can be inferred.

> I'm not sure whether you're saying that your C# version of MinElement
> would work or not.

I want it to work but I think it is currently not supposed to work.
From the documentation on generics I have seen so far, I have not seen
any example [I can also remember] which indicates that my 'MinElement()'
function is working. I would be delighted to hear the contrary! As
mentioned, I'm currently, unfortunately, not in the position to try
things out.

> If MinElement would work, can you supply a simple
> example of a STL-like algorithm that wouldn't work?

I think I would be able to implement C# versions of all STL algorithms
if it works to infer a few associated types. I don't think that it is
possible or feasible to implement some of the finer points like doing
certain optimizations or taking advantage of specific properties but
the user interface could be made similar.

andrew queisser

unread,
Oct 9, 2003, 11:22:43 AM10/9/03
to

"Dietmar Kuehl" <dietma...@yahoo.com> wrote in message
news:OIa3r4dj...@TK2MSFTNGP12.phx.gbl...

> andrew queisser wrote:
> > I'm not sure whether you're saying that your C# version of MinElement
> > would work or not.
>
> I want it to work but I think it is currently not supposed to work.
> From the documentation on generics I have seen so far, I have not seen
> any example [I can also remember] which indicates that my 'MinElement()'
> function is working. I would be delighted to hear the contrary! As
> mentioned, I'm currently, unfortunately, not in the position to try
> things out.

I think I understand now. In the MinElement example the type parameter
T shows up only in the constraint, not as a type parameter to the class
algos itself. From Jason Clark's October MSDN magazine article
(http://msdn.microsoft.com/msdnmag/issues/03/10/NET/default.aspx)
we know that a constraint can be a generic interface but we don't know
whether a constraint's type parameter has to show up in the type parameter
list of the class itself.

Could generic delegates be of any help?

Andrew


Dietmar Kuehl

unread,
Oct 9, 2003, 3:39:29 PM10/9/03
to
andrew queisser wrote:
> Could generic delegates be of any help?

I don't see how. The tricky part is that it cannot be told a priori
what type is returned from a particular function. We might expect a
certain interface about these types but we cannot tell the exact
type.

0 new messages