Reputation: 55
I'm new to C# and trying to figure out how i can easily implement the following:
I have a subscriber:
public interface ISubscriber
{
void HandleMessage(IMessage message);
}
class TriggerSubscriber : ISubscriber
{
public void HandleMessage(IMessage message)
{
//This will be called by default
}
public void HandleMessage(TriggerMessage message)
{
//This won't work, why?
}
}
Trying to handle the following message:
public class TriggerMessage : IMessage
{
string identifier { get; set; }
public TriggerMessage(string triggerIdentifier)
{
identifier = triggerIdentifier;
}
}
public interface IMessage
{
}
I expected that the following would have been called:
public void HandleMessage(TriggerMessage message)
instead of
public void HandleMessage(IMessage message)
with
ISubscriber trigger = new TriggerSUbscriber();
trigger.HandleMessage(
new TriggerMessage()
);
Am i missing something here?
Upvotes: 4
Views: 1014
Reputation: 28272
Your trigger
variable is defined as it being of type ISubscriber
(no matter what the actual object type is). ISubscriber
only has one method signature:
void HandleMessage(IMessage message);
So the compiler calls that method.
In fact, if you did this:
class TriggerSubscriber : ISubscriber
{
public void HandleMessage(IMessage message)
{
}
public void HandleMessage(int something)
{
}
}
And then try to do this:
ISubscriber trigger = new TriggerSubscriber();
trigger.HandleMessage(4);
The compiler will complain that there's no such method in ISubscriber
which takes an int
parameter.
There are three options:
TriggerMessage
method to the interfaceDeclare your trigger
variable as TriggerSubscriber
, instead of as ISubscriber
, or cast it to TriggerSubscriber
when calling HandleMessage
:
((TriggerSubscriber)trigger).HandleMessage(new TriggerMessage());
Solve it in the implementation:
class TriggerSubscriber : ISubscriber
{
public void HandleMessage(IMessage message)
{
var triggerMessage = message as TriggerMessage;
if(triggerMessage != null)
{
// Casting is not necessary, but I'd still put it
// here just to make it clear
HandleMessage((TriggerMessage)triggerMessage);
return;
}
// other code
}
public void HandleMessage(TriggerMessage message)
{
}
}
I'd definitely use #3 (and I'd call the method that receives a TriggerMessage
something like HandleTriggerMessage
, instead of having possible ambiguities), but you choose
Upvotes: 6
Reputation: 156918
Yes, trigger
is of type ISubscriber
which only has one HandleMessage
method defined in its interface:
void HandleMessage(IMessage message)
There is no other method to match from the interface definition, so that only visible method is called. There is no overload resolution taking place here.
If you change ISubscriber trigger
to TriggerSubscriber trigger
(now there are two methods visible!) you will see you get the expected method called.
Upvotes: 2