Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

When is using IS and AS okay? How would you refactor this?

I know that similar questions might have been asked before, but I am looking for an alternatvie solution to using IS, as I have read that IS is considered evil in the top-comment here.

So basically my Problem is that I have Abilities and Objects (Object A and Object B) that can use said abilities. However Object A lacks some data/information meaning it can only use some types of abilities (Ability A), while Object B has should be able to use all Abilities of type A and in addition some of type B.

For now I solved this the following way:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

public abstract class BaseEffect
{
}
public abstract class GeneralEffect : BaseEffect
{
    public abstract void Trigger(int damage, float factor);
}
public class GeneralEffectTest : GeneralEffect
{
    public override void Trigger(int damage, float factor)
    {
        Console.WriteLine("Deal " + damage * factor + " damage");
    }
}
public abstract class PlayerEffect : BaseEffect
{
    public abstract void Trigger(int damage, string text, float factor);
}
public class PlayerEffectTest : PlayerEffect
{
    public override void Trigger(int damage, string playerOnlyInfo, float factor)
    {
        Console.WriteLine("Deal " + damage * factor + " " + text + "-damage");
    }
}

And basically a class that would be able to use both types of effects is the following:

public class TestClass
{
    public BaseEffect effect;

    public TestClass()
    {
        effect = new PlayerEffectTest();
    }

    public void Trigger()
    {
        if (effect is GeneralEffect)
        {
            ((GeneralEffect)effect).Trigger(2, 0.5f);
        }
        else if (effect is PlayerEffect)
        {
            ((PlayerEffect)effect).Trigger(2, "Fire", 0.2f);
        }
    }
}

A class that would be able to use just GeneralEffects would on the other hand just have a field defining a GeneralEffect.

I should maybe also note that for my actual use-case I would iterate through a List/Array of Effects.

Is there any way to avoid the "evil" IS here? How would you solve that issue?

>Solution :

is isn’t evil. Everything depends on its usage. In fact, is can be used since C# 7 in pattern matching which would allow you to write :

if (effect is GeneralEffect ge)
{
    ge.Trigger(2, 0.5f);
}
else if (effect is PlayerEffect pe)
{
    pe.Trigger(2, "Fire", 0.2f);
}

An even better option would be to use pattern matching with switch :

switch(effect)
{
    case PlayerEffect pe:
        pe.Trigger(2, "Fire", 0.2f);
        break;
    case GeneralEffect ge:
        ge.Trigger(2, 0.5f);
        break;
}

Pattern matching is far more powerful than this, as you can match on properties, not just types. It’s also possible to add guard clauses:

switch(effect)
{
    case PlayerEffect pe when player.Ammo>0:
        pe.Trigger(2, "Fire", 0.2f);
        break;
    case PlayerEffect pe:
        pe.Trigger(0, "Click", 0.0f);
        break;
    case GeneralEffect ge:
        ge.Trigger(2, 0.5f);
        break;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading