Generics, constraints and overloading

P

Pierre Arnaud

I'd like to provide two generic methods with the same name and
the same arguments, but with different constraints, such as:

void Explore<T>(T[] a, T[] b) where T : struct { }
void Explore<T>(T[] a, T[] b) where T : class { }

The value types should use the first method and the reference types
the second method. However, this won't compile, as the C# compiler
reports that there is already a method defined with the same name
and the same arguments.

Constraints seem not to be taken in account !?

Is there some other means of handling value and reference types
in different methods automatically ? I can't see one with generics
in C#. But I might have overlooked something.

Pierre

http://www.creativedocs.net/
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,


Is the handling of those two cases so different that you need two methods?
You can use Type.IsClass to see if it's a class or not. you can have an if
statement and do what you need in any case.
 
P

Pierre Arnaud

Ignacio said:
Hi,


Is the handling of those two cases so different that you need two
methods? You can use Type.IsClass to see if it's a class or not. you
can have an if statement and do what you need in any case.

It's just an optimization issue:

- If it is a class type, then I have to do some checking to see if the
parameters are null; and I can compare for reference equality and need
to be prudent when calling object.Equals(object)

- If it is a struct type, I don't need to check for null and Equals can
be used without afterthought (or even System.IEquatable<T>.Equals)

You see the idea. If I want to do some null checking in my method, I
can't use a generic type for which T is not specified to be of class
type. And if I do, I can't pass value types to my method...

Pierre
 
K

Kevin Yu [MSFT]

Hi Pierre,

Ignacio has provided us with a good way of idetifying if a type is a class.
In your method, you can first use IsClass to check if T is a reference type
like the following:

if(typeof(T).IsClass)
.....//for reference types
else
.....//for value types

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,
It's just an optimization issue:

- If it is a class type, then I have to do some checking to see if the
parameters are null; and I can compare for reference equality and need
to be prudent when calling object.Equals(object)

- If it is a struct type, I don't need to check for null and Equals can
be used without afterthought (or even System.IEquatable<T>.Equals)

Then Type.IsClass or Type.IsValueType is your answer
 
P

Pierre Arnaud

Kevin said:
Hi Pierre,

Ignacio has provided us with a good way of idetifying if a type is a
class. In your method, you can first use IsClass to check if T is a
reference type like the following:

if(typeof(T).IsClass)
....//for reference types
else
....//for value types

No, sorry, this won't work for me, as I want this test to be done at
compile time, not at run time. Here is a sample of what I want to be
able to do:

class Foo
{
public static bool Test<T>(T[] array) where T : struct
{
return (array[0] == array[1]);
}

public static bool Test<T>(T[] array) where T : class
{
return (array[0] == array[1])
&& (array[0] != null)
&& (array[1] != null);
}
}

I can't do the "== null" test if T is a value type, as it won't
compile. So how do I implement something which does this? I had
expected that the "where T : struct" and "where T : class"
constraints would be sufficient for the compiler to tell both
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

I can't do the "== null" test if T is a value type, as it won't
compile. So how do I implement something which does this?

As I said before, you use either IsClass or IsValueType to decide which is.
 
P

Pierre Arnaud

Ignacio said:
Hi,



As I said before, you use either IsClass or IsValueType to decide
which is.

Sorry, no. I can't write :

class Foo
{
public static bool Test<T>(T[] array)
{
if (typeof (T).IsValueType)
{
return (array[0].Equals (array[1]));
}
if (typeof (T).IsClass)
{
return (array[0] == array[1]) // <--- here
&& (array[0] != null)
&& (array[1] != null);
}
throw new System.InvalidOperationException ();
}
}

as it won't compile. The C# compiler does not know "here"
that both array[0] and array[1] refer to reference types,
so it can't resolve the "==" ...
 
K

Kevin Yu [MSFT]

Hi,

Can you try to override the Object.Equal method and use return
(Object.Equal(array[0] == array[1]))?

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
P

Pierre Arnaud

Kevin said:
Hi,

Can you try to override the Object.Equal method and use return
(Object.Equal(array[0] == array[1]))?

Oh, yes. Object.Equal(array[0], array[1]) would do the trick.
Thanks for this (obvious -- but I hadn't seen it) solution.
 
K

Kevin Yu [MSFT]

You're welcome!

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 

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