views:

238

answers:

2

I am using the Visio API to loop through each Microsoft.Office.Interop.Visio.Master object in a Microsoft.Office.Interop.Document's Masters collection.

When I use var as follows, the compiler only recognizes master as type object and throws an error:

foreach (var master in doc.Masters)

Instead, I have to do this for it to work:

foreach (Visio.Master master in doc.Masters)

Why is this happening? Usually I have no problems using var in a foreach loop.

Edit: the error I get when I use the Open method on master is:

'object' does not contain a definition for 'Open' and no extension method 'Open' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)

+15  A: 

My guess is that doc.Masters is returning IEnumerable or IEnumerable<object> - i.e. it's weakly typed.

Basically there's an implicit cast in the second version - it's doing (assuming the non-generic form):

using (IEnumerator enumerator = doc.Masters.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        Visio.Master master = (Visio.Master) enumerator.Current;
        // Loop body
    }
}

It only knows what type you're interested in because you've specified that as the type for the variable. (This is a bit like specifying the type of a range variable, which makes the compiler call Cast<T>() in the expansion of a LINQ query expression.)

Jon Skeet
It is definitely weakly typed, because it comes from COM - and all COM-originated sequences are plain `IEnumerable`s (because there's nowhere to get type annotations for elements from).
Pavel Minaev
@Pavel: That's what I was guessing, but my COM knowledge is as weak as the collections it exposes ;)
Jon Skeet
+2  A: 

The var keyword doesn't work whenever the collection (or whatever you use it for) is not strongly typed. In other words: When it is clear that the right side of the expression returns a certain type, the var works.

Example:

var name = "Markus";   // Must be string
var form = new Form(); // Must be form

However, when the type is 'object', then var will also represent an object.

Example:

var myList = new ArrayList(); // var = ArrayList
foreach (var item in myList) // item = object
{ }

However, if the list is strongly typed, var will work as expected:

var myList = new List<string>();
foreach (var item in myList)  // item = string
{ }

I do not know the Visio API, but my assumption would be that var turns into an object and thus is not very useful to you.