Seeing as C# can\'t switch
on a Type (which I gather wasn\'t added as a special case because is
relationships mean that more than one distinct
Create an interface IFooable
, then make your A
and B
classes to implement a common method, which in turn calls the corresponding method you want:
interface IFooable
{
public void Foo();
}
class A : IFooable
{
//other methods ...
public void Foo()
{
this.Hop();
}
}
class B : IFooable
{
//other methods ...
public void Foo()
{
this.Skip();
}
}
class ProcessingClass
{
public void Foo(object o)
{
if (o == null)
throw new NullRefferenceException("Null reference", "o");
IFooable f = o as IFooable;
if (f != null)
{
f.Foo();
}
else
{
throw new ArgumentException("Unexpected type: " + o.GetType());
}
}
}
Note, that it's better to use as
instead first checking with is
and then casting, as that way you make 2 casts, so it's more expensive.
Should work with
case type _:
like:
int i = 1;
bool b = true;
double d = 1.1;
object o = i; // whatever you want
switch (o)
{
case int _:
Answer.Content = "You got the int";
break;
case double _:
Answer.Content = "You got the double";
break;
case bool _:
Answer.Content = "You got the bool";
break;
}
Given inheritance facilitates an object to be recognized as more than one type, I think a switch could lead to bad ambiguity. For example:
Case 1
{
string s = "a";
if (s is string) Print("Foo");
else if (s is object) Print("Bar");
}
Case 2
{
string s = "a";
if (s is object) Print("Foo");
else if (s is string) Print("Bar");
}
Because s is a string and an object.
I think when you write a switch(foo)
you expect foo to match one and only one of the case
statements. With a switch on types, the order in which you write your case statements could possibly change the result of the whole switch statement. I think that would be wrong.
You could think of a compiler-check on the types of a "typeswitch" statement, checking that the enumerated types do not inherit from each other. That doesn't exist though.
foo is T
is not the same as foo.GetType() == typeof(T)
!!
As Pablo suggests, interface approach is almost always the right thing to do to handle this. To really utilize switch, another alternative is to have a custom enum denoting your type in your classes.
enum ObjectType { A, B, Default }
interface IIdentifiable
{
ObjectType Type { get; };
}
class A : IIdentifiable
{
public ObjectType Type { get { return ObjectType.A; } }
}
class B : IIdentifiable
{
public ObjectType Type { get { return ObjectType.B; } }
}
void Foo(IIdentifiable o)
{
switch (o.Type)
{
case ObjectType.A:
case ObjectType.B:
//......
}
}
This is kind of implemented in BCL too. One example is MemberInfo.MemberTypes, another is GetTypeCode
for primitive types, like:
void Foo(object o)
{
switch (Type.GetTypeCode(o.GetType())) // for IConvertible, just o.GetTypeCode()
{
case TypeCode.Int16:
case TypeCode.Int32:
//etc ......
}
}
I use
public T Store<T>()
{
Type t = typeof(T);
if (t == typeof(CategoryDataStore))
return (T)DependencyService.Get<IDataStore<ItemCategory>>();
else
return default(T);
}
You can create overloaded methods:
void Foo(A a)
{
a.Hop();
}
void Foo(B b)
{
b.Skip();
}
void Foo(object o)
{
throw new ArgumentException("Unexpected type: " + o.GetType());
}
And cast the argument to dynamic type in order to bypass static type checking:
Foo((dynamic)something);