В этих строках кода:
int countnumM = tab2table.AsEnumerable()
.Select(x => int.TryParse(x["MLevel"].ToString(), out var d) ? d : (int?)null)
.Where(x => x >= 1 && x <= 4).Count();
int countnumRW = tab2table.AsEnumerable()
.Select(x => int.TryParse(x["RLevel"].ToString(), out var d) ? d : (int?)null)
.Where(x => x >= 1 && x <= 4).Count();
Вы используете int.TryParse
, чтобы прочитать значение x["MLevel"]
.
Если x["MLevel"].ToString()
не возвращает string
, который может быть проанализирован как int
, тогда int.TryParse
вернет false. Это включает, если x
равно DBNull.Value
. Это не будет проанализировано как int
.
Затем, после TryParse
, у вас есть это: ? d : (int?)null)
Другими словами, если TryParse
вернул true - он был в состоянии проанализировать, то вы выбираете d
- проанализированное значение.
Но если он не смог разобрать значение - TryParse
вернул false - тогда вы вернете (int?)null
- что фактически равно нулю.
В конце вы фильтруете результаты по значениям от 1 до 4, а затем подсчитываете количество этих результатов:
.Where(x => x >= 1 && x <= 4).Count();
Как вы и описали, если бы было несколько ненулевых значений, то Count
, вероятно, вернет одно или несколько. Но если есть все нулевые значения, то .Count
будет равно 0, потому что между 1 и 4 не было значений.
В этом случае countnumM
и / или countnumRW
будет равно 0.
Далее вы устанавливаете некоторые дополнительные значения if countnumM > 0
и if countnumRW > 0
. Но они не больше 0. Они равны 0. Если они равны 0, ваш код будет делать то, что вы ожидаете:
for (int i = 1; i < 5; i++)
{
if (countnumM > 0) // this is == 0
{
float levelPercM = Convert.ToInt32(tab2table.Compute("COUNT(MLevel)", "MLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][1] = Math.Round(100 * levelPercM / countnumM, 2);
}
else // This is what's happening
tab2tableExtra.Rows[i - 1][1] = null;
if (countnumRW > 0) // this is == 0
{
decimal levelPercRW = Convert.ToDecimal(tab2table.Compute("COUNT([RLevel])", "RLevel =" + i.ToString()));
tab2tableExtra.Rows[i - 1][2] = Math.Round(100 * levelPercRW / countnumRW, 2);
}
else // This is what's happening
tab2tableExtra.Rows[i - 1][2] = null;
}
Чтобы уточнить вокруг другой части - InvalidOperationException
:
Когда вы находитесь в отладчике и проверяете свойства переменной, он попытается отобразить значение каждого свойства. Вот что список свойств в вашем изображении - это все свойства this
.
Некоторые из них могут быть свойствами, которые вы не используете или не интересуете, но когда он пытается прочитать свойства, чтобы показать их вам, свойство выдает исключение. Так что теперь вместо значения свойства он показывает исключение, которое он получил при попытке прочитать свойство.
Это понятно сбивает с толку, потому что вы отлаживаете, пытаясь выяснить, что происходит в вашем коде, и затем вы видите исключения. Вы задаетесь вопросом, могут ли они быть связаны с проблемой.
Как правило, это не так, потому что если ваш код выдает исключение, то он останавливает выполнение вашего кода. Это исключение, которое вы должны выяснить. Но если это не мешает вашему коду работать и это свойство некоторого каркасного класса (например, Form.AccessibilityObject
), которое вы даже не используете, то вы обычно можете его игнорировать.