Implementing "Is" C# in C++, msdn article

  • Thread starter Thread starter nicolas.hilaire
  • Start date Start date
N

nicolas.hilaire

Hi all,

i've read this article
http://msdn2.microsoft.com/en-us/library/85af44e9.aspx who first
interest me much.
I've translated it to use generic instead of template :

generic < typename T, typename U >
Boolean isinst(U u)
{
return safe_cast< T >(u) != nullptr;
}

but i realised that this can't be really a good solution. For example,
this example :

Collections::ArrayList^ a = gcnew Collections::ArrayList();
if ( isinst< Collections::ICollection ^ >(a) )
Console::WriteLine("a is a ICollection ");

We can understand that the safe_cast is working, so the function
returns true.

Before reading this article, I used to compare object with such a way :

if (a->GetType() == Collections::ICollection::typeid)
Console::WriteLine("a is a ICollection ");

In this example, the if statement is false, because a is not a
ICollection.

Can you explain me where i am wrong ? Or is the Msdn article incomplete
?

Thanks in advance for your answers,

Nico
 
Hi all,

i've read this article
http://msdn2.microsoft.com/en-us/library/85af44e9.aspx who first
interest me much.
I've translated it to use generic instead of template :

generic < typename T, typename U >
Boolean isinst(U u)
{
return safe_cast< T >(u) != nullptr;
}

but i realised that this can't be really a good solution. For example,
this example :

Collections::ArrayList^ a = gcnew Collections::ArrayList();
if ( isinst< Collections::ICollection ^ >(a) )
Console::WriteLine("a is a ICollection ");

This is testing for assignment compatibility - a Collections::ArrayList
instance can be assigned to a variable of type ICollection.
We can understand that the safe_cast is working, so the function
returns true.

Before reading this article, I used to compare object with such a way :

if (a->GetType() == Collections::ICollection::typeid)
Console::WriteLine("a is a ICollection ");

In this example, the if statement is false, because a is not a
ICollection.

This is testing for type identity - the type of a Collection::ArrayList is
exactly the type Collections::ArrayList and nothing else.
Can you explain me where i am wrong ? Or is the Msdn article incomplete
?

You're testing two different things, both are valid in some context.
Generally, assignment compatibility is what you're interested in. If you're
checking for type identity, you're probably not structuring your code
correctly, as tests for type identity (e.g. switch on type) can usually be
better handled by virtual functions.

-cd
 
You're testing two different things, both are valid in some context.
Generally, assignment compatibility is what you're interested in. If you're
checking for type identity, you're probably not structuring your code
correctly, as tests for type identity (e.g. switch on type) can usually be
better handled by virtual functions.


Thanks for your answer,

I've never done c#, but i thought that the "Is" keyword was the same as
in VB.Net.

I thought to use this as in this example, to empty textbox control only
on my form :

for each (Control ^c in this->Controls)
if (c->GetType() == TextBox::typeid)
c->Text = "";

in VB, i probably had used the Is keyword to know if "c Is Textbox Then
...." ; but maybe in C# "Is" hasn't the same meaning.


Do you think here that I can avoid testing for type identity ?
Could you give me an example where testing for assignement can be
useful ? Usually, i know if I can cast something to something else ...
maybe in generics function ?

Best regards,

Nicolas H.
 
Your code for the equivalent of the C# "is" is correct.
i.e.,
if (a->GetType() == Collections::ICollection::typeid)
is equivalent to:
if (a is Collections::ICollection)

(regarding your follow-up post, "is" in C# is not the same as "Is" in VB).

The MSDN article, despite it's title, does not explain the C++/CLI
equivalent to the C# "is".
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
Instant C++: C# to C++ converter & VB to C++ converter
Instant J#: VB to J# converter
 
David said:
Your code for the equivalent of the C# "is" is correct.
i.e.,
if (a->GetType() == Collections::ICollection::typeid)
is equivalent to:
if (a is Collections::ICollection)

No, it's not. C#'s 'is' is tests for assignment compatibility (or reference
convertability - same thing for this purpose).

In C++/CLI, dynamic_cast<T>(e) is equivalent to C#'s 'as' operator: e as T,
while safe_cast<T>(e) is equivalent to C#'s cast: (T)e.

The C# 'is' operator has no direct equivalent in C++/CLI, but is
functionally equivalent to dynamic_cast<T>(e) != nullptr, as illustrated in
the MSDN article mention in the original post of this thread.

Note that using constructs like

if (e is T)
{
T t = e as T;
// ...
}

is bad (but common) practice - and FxCop will warn you about it. Under the
covers, is and as are both doing a cast, so the above code needlessly
performs two identical casts in succession. In C# (or C++/CLI), it's more
efficient (and encouraged by FxCop and the .NET design guidelines) to write:

T t = e as T;
if (null != t)
{
// ...
}

or in C++/CLI

T t = dynamic_cast<T>(e);
if (t != nullptr)
{
// ...
}

-cd
 
Thanks for your answer,

I've never done c#, but i thought that the "Is" keyword was the same
as
in VB.Net.

The 'Is' operator in Vb.Net is somewhat different. In most cases, it's
syntactic sugar around a call to System::Obect::ReferenceEquals(e1, e2) -
except when it's used in an expression of the form If TypeOf e Is t, in
which case it's equivalent to C#'s 'is' operator.
I thought to use this as in this example, to empty textbox control
only
on my form :

for each (Control ^c in this->Controls)
if (c->GetType() == TextBox::typeid)
c->Text = "";

in VB, i probably had used the Is keyword to know if "c Is Textbox
Then ..." ; but maybe in C# "Is" hasn't the same meaning.

In C# you'd use 'is' in this case. In C++/CLI, you should use dynamic_cast.
Do you think here that I can avoid testing for type identity ?

It depends on what you intend to do. In this case, it looks like you're aim
is to clear the text from all text boxes, in which case type identity is
what you want.
Could you give me an example where testing for assignement can be
useful ? Usually, i know if I can cast something to something else ...
maybe in generics function ?

It's more likely to be useful in a generic function, but there are
non-generic cases as well.

For example, you might have a centrailzed Log() function that has special
support for logging collections, so inside such a hypothetical function you
might write:

void Log(object o)
{
if (o is ICollection)
{
// special ICollection logging
}
else
{
// non-ICollection logging
}
}

Here you're doing the functional equivalent of adding a virtual function to
System.Object, then overriding it in ICollection (neither of which is
actually possible, but you get the same effect).

Does that help?

-cd
 
The following test whether 'a' is of type Collections::ICollection in C#:
if (a is Collections::ICollection)

The following tests whether 'a' is of type Collections::ICollection in
C++/CLI:
if (a->GetType() == Collections::ICollection::typeid)

There may be other ways of doing this in C++, but the above method is valid.
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
Instant C++: C# to C++ converter & VB to C++ converter
Instant J#: VB to J# converter
 
ok, thanks for your help ...
in fact i was totaly lost with the As operator (i didn't know)

And i made a mistake with the dynamic_cast (and the safe_cast)

Then,
I've this method, coming from the Msdn article

template < class T, class U >
Boolean isinst(U u) {
return dynamic_cast< T >(u) != nullptr;
}

and this generic one i've made

generic <typename T, typename U>
bool is(U u)
{
return T::typeid == u->GetType();
}

This both method seems to do the same things (correct me if i'm wrong).
Should i prefer the dynamic_cast one, or the one that uses reflexion ?

Thanks for your answer,

Greats,

Nico
 
In C# you'd use 'is' in this case. In C++/CLI, you should use dynamic_cast

you're answered while i was typing ...

Why prefering dynamic_cast ? to be more efficient ? Reflexion is a bad
idea ?


Greats,

Nicolas H
 
David said:
The following test whether 'a' is of type Collections::ICollection in
C#:
if (a is Collections::ICollection)

No, it does not. This tests whether the type of a is assignment compatible
with Collections::ICollection.
The following tests whether 'a' is of type Collections::ICollection in
C++/CLI:
if (a->GetType() == Collections::ICollection::typeid)

This checks for type identify, as I said in the earlier post. The 'is'
keywork in C# does not test for type identity, but for type convertibility.
There may be other ways of doing this in C++, but the above method is
valid. --

Valid yes, but not equivalent - and producing different results in more
cases than not.

The above C++/CLI code is equivalent to the following C# code:

if (a.GetType() == typeof(Collections.ICollection))

-cd
 
you're answered while i was typing ...

Why prefering dynamic_cast ? to be more efficient ? Reflexion is a bad
idea ?

C#'s is and C++/CLI's dynamic_cast are identical - they generate identical
IL code. ALL casts in IL are dynamic, based on type metadata.

-cd
 
I should just stop myself after sticking my foot in my mouth earlier, but
don't you mean that C# "as" and "dynamic_cast" are equivalent? (not "is" and
"dynamic_cast"...?)
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
Instant C++: C# to C++ converter & VB to C++ converter
Instant J#: VB to J# converter
 
"Carl Daniel [VC++ MVP]" <[email protected]>
wrote in message | (e-mail address removed) wrote:
| >> In C# you'd use 'is' in this case. In C++/CLI, you should use
| >> dynamic_cast
| >
| > you're answered while i was typing ...
| >
| > Why prefering dynamic_cast ? to be more efficient ? Reflexion is a bad
| > idea ?
|
| C#'s is and C++/CLI's dynamic_cast are identical - they generate identical
| IL code. ALL casts in IL are dynamic, based on type metadata.
|
| -cd
|
|

I'm sure you meant:

C#'s as and C++/CLI's dynamic_cast are identical ..

Willy.
 
Willy Denoyette said:
I'm sure you meant:

C#'s as and C++/CLI's dynamic_cast are identical ..

Indeed, yes! I think I said it correctly somewhere else in the thread :)

-cd
 
I'm sure you meant:
Indeed, yes! I think I said it correctly somewhere else in the thread :)

I'm a bit confused ...

if I've well understood, could i write the "as" and the "is" operator
like this ?

template < class T, class U >
Boolean is(U u)
{
return dynamic_cast< T >(u) != nullptr;
}

template < class T, class U >
T as(U u)
{
return dynamic_cast< T >(u);
}

Nicolas
 
I'm a bit confused ...

if I've well understood, could i write the "as" and the "is" operator
like this ?

template < class T, class U >
Boolean is(U u)
{
return dynamic_cast< T >(u) != nullptr;
}

template < class T, class U >
T as(U u)
{
return dynamic_cast< T >(u);
}

You're not confused :)

-cd
 
Thanks for your help Carl,

this is really much clearer now.

Thanks to other too, your help was usefull to me too.


Best regards,

Nicolas H.
 
Back
Top