compiler not detecting type using var keyword in visual studio

In the following code, row is considered as object and not DataGridViewRow.

foreach (var row in datagridview.Rows)
{
   row.Visible = false  //<- error because no Visible property
}

Am I missing something? shouldn't row be DataGridViewRow?

Upvotes: 0

Views: 398

Answers (5)

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

DataGridView.Rows is a collection which inherits from IEnumerable not IEnumerable<T> so you will need to use OfType<T>() or Cast<T>() to convert it to IEnumerable<T> which are under System.Linq namespace, so you have to add using System.Linq in your code file:

foreach (var row in datagridview.Rows.OfType<DataGridViewRow)
{
   row.Visible = false  //<- error because no Visible property
}

or you can cast it in foreach to DataGridViewRow, if you dont want to use Cast<T>() or OfType<T>():

foreach (DataGridView row in datagridview.Rows)
{
   row.Visible = false  //<- error because no Visible property
}

Upvotes: 2

Alex
Alex

Reputation: 13224

Your call to datagridview.Rows returns an instance of type DataGridViewRowCollection, which implements the non-generic ICollection, IEnumerable and IList interfaces, thus, when you do "foreach" it will return instances of type System.Object.

When using an implicitly typed variable with the var row statement, the type of the row variable will now become System.Object.

To solve this, you can specify the type for row explicitly in the foreach statement:

foreach (DataGridViewRow row in datagridview.Rows)
{
   row.Visible = false;
}

This works, because the foreach implementation silently performs an explicit conversion (cast) of each object returned from the Enumerator.Current to type DataGridViewRow, as you can read about here.

Upvotes: 6

harsimranb
harsimranb

Reputation: 2283

You have to specifically set the type to DataGridViewRow. Here's why:

DataGridView.Rows is of type DataGridViewSelectedRowCollection. If we refractor that class, we get this:

public class DataGridViewSelectedRowCollection : BaseCollection, IList 

The type is never specified, there are no generics used, just Plain old collections.

Therefore, .net cannot automatically infer a type. You have to specifically set the type to DataGridViewRow.

I'm guessing this is from the .Net days, when there were no generics.

Upvotes: 0

Jon Hanna
Jon Hanna

Reputation: 113242

DataGridViewRowCollection implements IEnumerable but not IEnumerable<DataGridViewRow>.

As such, it gives you a sequence of object not of DataGridViewRow.

Now the form:

foreach(DataGridViewRow row in datagridview.Rows)
{
   row.Visible = false;
}

... will work, because foreach involves in inherent cast.

This was a great convenience in the days of .NET1.0 and 1.1 when there were no generics and as such not generic enumerators. Today it's less useful than it was (especially as it means some things that will not work at runtime will still compile, that could be caught without this inherent cast), but it will work for you here.

var though will always be of the type of the expression, which in this case is object.

Upvotes: 0

theAnubhav
theAnubhav

Reputation: 533

try this;

for(var i =0;i< datagridview.Rows.Count;i++)
{ var row = datagridview.Rows[i];
   row.Visible = false  
}

Upvotes: 0

Related Questions