Reputation: 2118
What is the difference between or is there any difference between:
myDgv.SelectedRows.Count
vs
myDgv.Rows.GetRowCount(DataGridViewElementStates.Selected)
in the context of a DataGridView, Windows Forms ?
Upvotes: 2
Views: 3500
Reputation: 4477
Microsoft suggest that SelectedCells
and to a lesser extent SelectedRows
are inefficient for large Data Sets, and that you should use GetCellCount
/GetRowCount
instead.
Upvotes: 1
Reputation: 2343
I think in the specific case you mention here there is very little difference between these two options aside from the order in which the data of your DataGridView will be processed. If you were saving off the intermediate objects that you're using to get the Count from you might be concerned that SelectedRows is presenting you with a static snapshot at the time that the reference is made but since both options are directly calling another method that shouldn't really be a factor here.
Whenever you're really curious about how to dig through something like this you can pop open ILDASM and browse into your GAC to see how the calls actually work.
From a somewhat high-level the distinction between using SelectedRows and Rows.GetCount() is that we're either getting a filtered collection and checking its size or getting the entire collection and filtering it down to a subset whose size we then retrieve. This is pretty much born out by what our IL for the initial usage shows us.
.method public hidebysig static void testDG() cil managed
{
// Code size 34 (0x22)
.maxstack 2
.locals init ([0] class [System.Windows.Forms]System.Windows.Forms.DataGridView dgvTest,
[1] int32 myNum,
[2] int32 otherum)
IL_0000: nop
IL_0001: newobj instance void [System.Windows.Forms]System.Windows.Forms.DataGridView::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance class [System.Windows.Forms]System.Windows.Forms.DataGridViewSelectedRowCollection [System.Windows.Forms]System.Windows.Forms.DataGridView::get_SelectedRows()
IL_000d: callvirt instance int32 [System.Windows.Forms]System.Windows.Forms.BaseCollection::get_Count()
IL_0012: stloc.1
IL_0013: ldloc.0
IL_0014: callvirt instance class [System.Windows.Forms]System.Windows.Forms.DataGridViewRowCollection [System.Windows.Forms]System.Windows.Forms.DataGridView::get_Rows()
IL_0019: ldc.i4.s 32
IL_001b: callvirt instance int32 [System.Windows.Forms]System.Windows.Forms.DataGridViewRowCollection::GetRowCount(valuetype [System.Windows.Forms]System.Windows.Forms.DataGridViewElementStates)
IL_0020: stloc.2
IL_0021: ret
} // end of method Program::testDG
As you likely suspect though this kind of begs the question of what these two lower-level calls do.
In this case the Rows property on the DataGridView creates an instance of the DataGridViewsRowCollection and passes it back since it maps to get_Rows.
.method public hidebysig specialname instance class System.Windows.Forms.DataGridViewRowCollection
get_Rows() cil managed
{
// Code size 27 (0x1b)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class System.Windows.Forms.DataGridViewRowCollection System.Windows.Forms.DataGridView::dataGridViewRows
IL_0006: brtrue.s IL_0014
IL_0008: ldarg.0
IL_0009: ldarg.0
IL_000a: callvirt instance class System.Windows.Forms.DataGridViewRowCollection System.Windows.Forms.DataGridView::CreateRowsInstance()
IL_000f: stfld class System.Windows.Forms.DataGridViewRowCollection System.Windows.Forms.DataGridView::dataGridViewRows
IL_0014: ldarg.0
IL_0015: ldfld class System.Windows.Forms.DataGridViewRowCollection System.Windows.Forms.DataGridView::dataGridViewRows
IL_001a: ret
} // end of method DataGridView::get_Rows
When we look at the SelectedRows property on the DataGridView we see that it's doing a lot more initially than just returning a collection but in the main try block we see our "get_Rows" call again (IL_0045).
.try
{
IL_0035: br.s IL_0056
IL_0037: ldloc.3
IL_0038: callvirt instance object [mscorlib]System.Collections.IEnumerator::get_Current()
IL_003d: unbox.any [mscorlib]System.Int32
IL_0042: stloc.1
IL_0043: ldloc.0
IL_0044: ldarg.0
IL_0045: call instance class System.Windows.Forms.DataGridViewRowCollection System.Windows.Forms.DataGridView::get_Rows()
IL_004a: ldloc.1
IL_004b: callvirt instance class System.Windows.Forms.DataGridViewRow System.Windows.Forms.DataGridViewRowCollection::get_Item(int32)
IL_0050: callvirt instance int32 System.Windows.Forms.DataGridViewSelectedRowCollection::Add(class System.Windows.Forms.DataGridViewRow)
IL_0055: pop
IL_0056: ldloc.3
IL_0057: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
IL_005c: brtrue.s IL_0037
IL_005e: leave.s IL_0074
} // end .try
This suggests that we're doing the same retrieval and filtering operations for our two choices and that the "cost" of doing them could be reasonably expected to be the same.
If you're noting performance issues around these calls you could run some tests to see if there is a difference but based on the IL I would be surprised if you found any appreciable distinction between the two calls
Upvotes: 2