0

I'm trying to iterate a list of forms (Mdichildren), and compare values of the specific forms in the list. However using var to encompass any type of Form makes it difficult to use form.Value that may be specific to a given form.

foreach (var oven in Ovens) // list of objects
{
    foreach (var form in this.Mdichildren) // contains multiple form types
    {
        if (form is Form_OvenControl)
        {
            if (oven.Id == form.ovenId)
            {
                // this fails because form.ovenId is treated like var, not like Form_OvenControl
            }
        }
        else if (form is Form_Instructions)
        {
            // do something with different type of form
        }
    }
}

I know I could cast the value and make a new variable of that type of form, but I want to use the object by reference in the list. I'm sure I could figure out a hacky way but I'm sure there's a neat way to do something (less illegal, but) like:

(Form_OvenControl)form.formSpecificValue = 0;

EDIT: as was kindly pointed out below, I can simply do the following:

if (form is Form_OvenControl)
{
    var ovenform = form as Form_OvenControl;
    if (oven.Id == ovenform.ovenId)
    {

    }
}

And the cast form will still refer to the item in the list I'm looking to alter.

I had just thought there was a way to use form as Form_OvenControl and access a variable within it essentially in one line.

Jay M
  • 57
  • 1
  • 8
  • if he property does not exists in the base class thn you will have to do a cast. And tbh try not to use var when its possible. Makes code a lot harder to read – Steve Aug 09 '16 at 20:24
  • 1
    Side note: you have some misconceptions about `var` - please make sure to read http://stackoverflow.com/questions/41479/use-of-var-keyword-in-c-sharp – Alexei Levenkov Aug 09 '16 at 20:26
  • What do you mean by _but I want to use the object by reference in the list_? Even if you create a new variable and cast it, it will still be referring to the `Form` in the list. – Chris Dunaway Aug 09 '16 at 20:48
  • @ChrisDunaway , thank you. In essence I guess I was poorly wording the question "does creating a new variable and casting it from an object in a list still refer to the item in the list if I change a value?" Thank you for being direct. – Jay M Aug 10 '16 at 12:09

2 Answers2

3
  1. It's not an "ambiguously typed object". What does that even mean? Where did you even get that from?

    It's a strongly typed variable whose type is determined by inference by the compiler. Probably Form in this case.

    It's just shorthand to save typing and visual clutter in cases where the compiler can infer the type from context:

    //  l is of type List<int> b/c duh
    var l = new List<int>();
    
    //  n must be int, because l is List<int>
    foreach (var n in l)
    {
    }
    

    That code will do exactly the same stuff as this code:

    List<int> l = new List<int>();
    
    foreach (int n in l)
    {
    }
    
  2. I know I could cast the value and make a new variable of that type of form, but I want to use the object by reference in the list

    Just cast it to the type it needs to be:

    if (form is Form_OvenControl)
    {
        var ovenform = form as Form_OvenControl;
        if (oven.Id == ovenform.ovenId)
        {
        }
    }
    else if (form is Form_Instructions)
    {
        var instform = form as Form_Instructions;
        // do something with different type of form
    }
    

UPDATE

In C#7...

    if (form is Form_OvenControl ovenform)
    {
        if (oven.Id == ovenform.ovenId)
        {
        }
    }
    else if (form is Form_Instructions instform)
    {
        // do something with instform
    }
  • 1
    your right casting into the concrete type is one possible solution. But I think it is bad practice to write those if -> elseif -> elseif -> elseif -> else structures. If you add a new Form type then you have to write a new if block. – whymatter Aug 09 '16 at 20:47
  • 2
    @whymatter Quite right. But this will get him moving for now. And I think Form isn't his class -- he'd have to define a common intermediate subclass. – 15ee8f99-57ff-4f92-890c-b56153 Aug 09 '16 at 20:55
1

You could define an virtual method on the class Form which is overridden in every inheritor. The implementation of the virtual method can handle what ever you need. And you can pass whatever you need as parameter.

Edit: Using virtual in case you have to instantiate From. This would not be possible with an abstract class.

class Program {
    static void Main(string[] args) {
        Form big = new FormBig();
        Form small = new FormSmall();

        big.DoJob(null); // FormBig
        small.DoJob(null); // FormSmall

        Console.ReadLine();
    }
}

class Form {
    public virtual void DoJob(object parametersYouNeed) {
        throw new NotImplementedException("use only on inheritor");
    }
}

class FormBig : Form {
    public override void DoJob(object parametersYouNeed) {
        Console.WriteLine("FormBig");
    }
}

class FormSmall : Form {
    public override void DoJob(object parametersYouNeed) {
        Console.WriteLine("FormSmall");
    }
}

Whenever you add a new Form type, you just have to implement the method DoJob and your code is working without modification.

This also meets the Open/Closed principle of S.O.L.I.D!


EDIT: if you can't make modifications on Form class

class Program {
    static void Main(string[] args) {
        FormMiddleMan big = new FormBig();
        FormMiddleMan small = new FormSmall();

        big.DoJob(null); // FormBig
        small.DoJob(null); // FormSmall

        Console.ReadLine();
    }
}

class Form {

}

abstract class FormMiddleMan : Form {
    public abstract void DoJob(object parametersYouNeed);
}

class FormBig : FormMiddleMan {
    public override void DoJob(object parametersYouNeed) {
        Console.WriteLine("FormBig");
    }
}

class FormSmall : FormMiddleMan {
    public override void DoJob(object parametersYouNeed) {
        Console.WriteLine("FormSmall");
    }
}

Define a FormMiddleMan class which inherits from Form class. It defines the DoJob method. Every of your concrete types inherits from FormMiddleMan and has to implement the DoJob method.

whymatter
  • 755
  • 8
  • 18