2 Questions on Casting

Posts   
 
    
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 05-Nov-2004 04:29:51   

Is there any difference at all between these two statements? ** Statement 1** IMyInterface obj = (IMyInterface)someVariable; ** Statement 2** IMyInterface obj = someVariable as IMyInterface

Is one safer than the other?

On to the next question. Suppose I have an interface ICommand. I then have another interface, ILateBoundCommand:ICommand. Lastly, I have a third interface ISmtpCommand:ILateBoundCommand.

ICommand defines a void, called ExecuteCommand. ILateBoundCommand contains definitions for properties, that could be used by reflection to load a type in an assembly and execute a method on that type. Lastly, ISmtpCommand contains the definition of a property that is of type System.Web.Mail.Message.

Assuming we have a class called DailyMailMessage that implements ISmtpCommand, we would have a class like so:


public class DailyMailMessage:ISmtpCommand
{
//... ISmtp Members
//... ICommand Members
//... ILateBoundCommandMembers
}

One could write a method like so:


//.... some code in the UI that creates a command object for a specific task being performed
public void DoSomething()
{
ProcessCommand(new DailyMailMessage)
}

//....  Some Class on another server that processes commands
public void ProcessCommand(ICommand command)
{
object tmpCommand = command as ISmtpCommand;
if (tmpCommand != null) 
{
QueueEmailCommand(tmpCommand as ISmtpCommand);
return;
}

tmpCommand = command as ILateBoundCommand;
if (tmpCommand != null)
{
ProcessLateBoundCommand(tmpCommand as ILateBoundCommand);
}
else
{
(tmpCommand as ICommand).Execute();
}

}

In the code above, we have passed in object that at some point implements ICommand. We do a lot of casting to determine which implementation to invoke. So the question is two fold; is the casting involved in the code above considered boxing / unboxing; AND is there a performance hit to do the multiple casting steps.

brettlj
User
Posts: 27
Joined: 08-Feb-2004
# Posted on: 05-Nov-2004 08:46:01   

Hey Devildog,

Devildog74 wrote:

Is there any difference at all between these two statements? ** Statement 1** IMyInterface obj = (IMyInterface)someVariable; ** Statement 2** IMyInterface obj = someVariable as IMyInterface

Is one safer than the other?

The main difference is that statement 1 will throw an exception if the cast isn't valid, statement 2 will not. I would generally regard statement 2 as 'safer', but I guess it depends on the context--you may want an exception to be thrown if someVariable is does not implement IMyInterface, depending on your exception handling strategy and other factors. Statement 2 would certainly perform better if someVariable doesn't inplement IMyInterface, as using 'as' and then testing for null doesn't incur near the overhead of catching an exception.

On to the next question. Suppose I have an interface ICommand. I then have another interface, ILateBoundCommand:ICommand. Lastly, I have a third interface ISmtpCommand:ILateBoundCommand.

ICommand defines a void, called ExecuteCommand. ILateBoundCommand contains definitions for properties, that could be used by reflection to load a type in an assembly and execute a method on that type. Lastly, ISmtpCommand contains the definition of a property that is of type System.Web.Mail.Message.

Assuming we have a class called DailyMailMessage that implements ISmtpCommand, we would have a class like so:


public class DailyMailMessage:ISmtpCommand
{
//... ISmtp Members
//... ICommand Members
//... ILateBoundCommandMembers
}

One could write a method like so:


//.... some code in the UI that creates a command object for a specific task being performed
public void DoSomething()
{
ProcessCommand(new DailyMailMessage)
}

//....  Some Class on another server that processes commands
public void ProcessCommand(ICommand command)
{
object tmpCommand = command as ISmtpCommand;
if (tmpCommand != null) 
{
QueueEmailCommand(tmpCommand as ISmtpCommand);
return;
}

tmpCommand = command as ILateBoundCommand;
if (tmpCommand != null)
{
ProcessLateBoundCommand(tmpCommand as ILateBoundCommand);
}
else
{
(tmpCommand as ICommand).Execute();
}

}

In the code above, we have passed in object that at some point implements ICommand. We do a lot of casting to determine which implementation to invoke. So the question is two fold; is the casting involved in the code above considered boxing / unboxing; AND is there a performance hit to do the multiple casting steps.

I don't believe this is considered boxing/unboxing since you're not dealing with primitive types, it is merely casting between types. There is a small perf hit with casting, but probably not much--certainly not as much as with boxing/unboxing.

Another approach would be to use the is operator, e.g.


if (command is ISmtpCommand) 
{
QueueEmailCommand(command as ISmtpCommand);
return;
}

This should work as long as you test in the right order--from the bottom of the inheritance hierarchy to the top, i.e. first test for ISmtpCommand, then ILateBoundCommand, etc.

Yet another approach that may work is to use overloaded methods:


public void ProcessCommand(ICommand command)
{
command.Execute();
}

public void ProcessCommand(ISmtpCommand command)
{
QueueEmailCommand(command);
}

public void ProcessCommand(ILateBoundCommand command)
{
ProcessLateBoundCommand(tmpCommand as ILateBoundCommand);
}


I like this approach because it is relatively clean...but the 'is' approach works well if you don't want to split your code up into a bunch of methods.

Also, I did post a late response to you in the 'Logging UserID of user performing action' thread: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=1288

Hadn't been on the forums for awhile, sorry for the late response!

Best, Brett

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 05-Nov-2004 13:44:15   

Thanks for the response and clarification.