bmw318mt Ответов: 2

Словарь C# получает нулевое исключение


У меня есть 2 класса (Parameter & ParameterGroup)

Я получаю нулевое исключение в строке при добавлении в словарь. pgName получается из базы данных. См. метод GetParameter ниже.

 ParameterGroup pg = parameterGroup
if  (!pg.ParametersGroups.TryGetValue(pgName, out pg))
                                        {
                                            ParameterGroup newPg = new ParameterGroup();
                                            pg.ParametersGroups.Add(pgName, newPg);
                                        }


Что я уже пробовал:

public class ParameterGroup
{
    private Dictionary<string, Parameter> _childsGroup;

    public Dictionary<string, Parameter> ChildsGroup
    {
        get { return _childsGroup; }
    }

    private Dictionary<string, ParameterGroup> _parametersGroup;

    public Dictionary<string, ParameterGroup> ParametersGroups
    {
        get { return _parametersGroup; }
    }
    public ParameterGroup()
    {
        _parametersGroup = new Dictionary<string, ParameterGroup>();
        _childsGroup = new Dictionary<string, Parameter>();
    }
}

public class Parameter
{
    private string _parameterName;

    public string ParameterName
    {
        get { return _parameterName; }
    }

    private double? _nominalValue;

    public double? NominalValue
    {
        get { return _nominalValue; }
    }

    private double? _upperTolerance;

    public double? UpperTolerance
    {
        get { return _upperTolerance; }
    }

    private double? _lowerTolerance;

    public double? LowerTolerance
    {
        get { return _lowerTolerance; }
    }

    public Parameter(string parameterName, double? nominalValue, double? upperTolerance, double? lowerTolerance)
    {
        _parameterName = parameterName;
        _nominalValue = nominalValue;
        _upperTolerance = upperTolerance;
        _lowerTolerance = lowerTolerance;
    }
}

public DBDriverResult GetParameters(string productCode, string processStep, string equipmentType,  out ParameterGroup parameterGroup)
       {
           DBDriverResult retVal = _defaultErrorResult;
           logMethodEntry(MethodBase.GetCurrentMethod(), productCode, processStep, equipmentType);

           //parameters = new Dictionary<string, Parameter>();
           parameterGroup = new ParameterGroup();

           using (OracleConnection db = connectToDB())
           {
               if (db != null)
               {
                   using (OracleCommand cd = db.CreateCommand())
                   {
                       cd.CommandType = CommandType.Text;
                       cd.CommandText = "SELECT * FROM TABLE(APCS.GetParametersByPPE(:p_ProductCode, :p_ProcessStep, :p_EquipmentType))";

                       cd.Parameters.Add(":p_ProductCode", productCode);
                       cd.Parameters.Add(":p_ProcessStep", processStep);
                       cd.Parameters.Add(":p_EquipmentType", equipmentType);


                       try
                       {
                           OracleDataReader r = cd.ExecuteReader();
                           if (r.HasRows)
                           {
                               while (r.Read())
                               {
                                   ParameterGroup pg = parameterGroup;
                                   string pgName;

                                   //Check if 1st root is null
                                   if (r["pg1"] != DBNull.Value)
                                   {
                                       pgName = (string)(r["pg1"]);

                                       if  (!pg.ParametersGroups.TryGetValue(pgName, out pg))
                                       {
                                           ParameterGroup newPg = new ParameterGroup();
                                           pg.ParametersGroups.Add(pgName, newPg);
                                       }

                                       if (r["pg2"] != DBNull.Value)
                                       {
                                           pgName = (string)(r["pg2"]);

                                           if (!pg.ParametersGroups.TryGetValue(pgName, out pg))
                                           {
                                               ParameterGroup newPg = new ParameterGroup();
                                               pg.ParametersGroups.Add(pgName, newPg);
                                           }

                                           if (r["pg3"] != DBNull.Value)
                                           {

                                               pgName = (string)(r["pg3"]);

                                               if (!pg.ParametersGroups.TryGetValue(pgName, out pg))
                                               {
                                                   ParameterGroup newPg = new ParameterGroup();
                                                   pg.ParametersGroups.Add(pgName, newPg);
                                               }
                                           }
                                       }
                                   }


                                   string parameterName   = (string)(r["ParameterName"]);
                                   double? nominalValue   = r["NominalValue"] == DBNull.Value ? null : (double?)r["NominalValue"];
                                   double? upperTolerance = r["UpperTolerance"] == DBNull.Value ? null : (double?)r["UpperTolerance"];
                                   double? lowerTolerance = r["LowerTolerance"] == DBNull.Value ? null : (double?)r["LowerTolerance"];


                                   Parameter p = new Parameter(parameterName, nominalValue, upperTolerance, lowerTolerance);
                                   pg.ChildsGroup.Add(parameterName, p);

                               }


                               r.Close();
                               retVal = DBDriverResult.DefaultSuccess;
                           }
                           else
                           {
                               // No rows returned, so equipment is unkown or disabled.
                               retVal = new DBDriverResult(DBDriverResultEnum.ddrRejected, "No Parameters found for Bond Program Recipe.");
                           }
                       }
                       catch (OracleException ex)
                       {
                           retVal = standardErrorHandler(ex, MethodBase.GetCurrentMethod().Name);
                       }

                   }
               }
           }

           logMethodExit(MethodBase.GetCurrentMethod(), retVal, parameterGroup);
           return retVal;
       }

Michael_Davies

Какая строка кода выдает ошибку? Вы использовали отладчик для пошаговой проверки переменной?

bmw318mt

Привет, это строка кода pg. ParametersGroups.Добавить (pgName, newPg);

получение нулевого исключения не может понять почему

Michael_Davies

Вы использовали отладчик, чтобы посмотреть на значение в pgName, newPG в порядке, так как вы только что выделили его, проверьте свой SQL-дамп ответа, чтобы вы могли видеть, что возвращается, и помните, что значения могут возвращать Null из базы данных, и вы всегда должны проверять их содержимое перед использованием.

bmw318mt

Да наведя курсор на pgName я могу получить строковое значение

Michael_Davies

ПГ? parameterGroup?

bmw318mt

они равны нулю

Michael_Davies

Тада! Теперь ты знаешь почему. Используйте отладчик для выполнения кода и убедитесь, что parameterGroup выделен перед его использованием.

2 Ответов

Рейтинг:
17

OriginalGriff

Это одна из самых распространенных проблем, которые нам задают, и это также та, на которую мы меньше всего готовы ответить, но вы больше всего готовы ответить сами.

Позвольте мне просто объяснить, что означает ошибка: вы пытались использовать переменную, свойство или возвращаемое значение метода, но оно содержит null - что означает, что в переменной нет экземпляра класса.
Это немного похоже на карман: у вас есть карман в рубашке, в котором вы держите ручку. Если вы сунете руку в карман и обнаружите, что там нет ручки, вы не сможете подписать свое имя на листе бумаги - и вы получите очень забавный вид, если попытаетесь! Пустой карман дает вам нулевое значение (здесь нет ручки!), поэтому вы не можете сделать ничего, что обычно делали бы, когда извлекли свою ручку. Почему он пуст? Вот в чем вопрос - может быть, вы забыли взять ручку, когда уходили из дома сегодня утром, или, возможно, вы оставили ручку в кармане вчерашней рубашки, когда снимали ее вчера вечером.

Мы не можем сказать, потому что нас там не было, и, что еще важнее, мы даже не можем видеть вашу рубашку, не говоря уже о том, что находится в кармане!

Вернемся к компьютерам, и вы каким - то образом сделали то же самое-и мы не можем увидеть ваш код, а тем более запустить его и узнать, что содержит null, когда это не должно быть.
Но вы можете - и Visual Studio поможет вам здесь. Запустите свою программу в отладчике, и когда она выйдет из строя, VS покажет вам строку, на которой она обнаружила проблему. Затем вы можете начать просматривать различные его части, чтобы увидеть, какое значение равно null, и начать просматривать свой код, чтобы выяснить, почему. Поэтому поставьте точку останова в начале метода, содержащего строку ошибки, и снова запустите программу с самого начала. На этот раз VS остановится перед ошибкой и позволит вам изучить, что происходит, пройдя через код, глядя на ваши значения.

Но мы не можем этого сделать - у нас нет вашего кода, мы не знаем, как его использовать, если бы он у нас был, у нас нет ваших данных. Так что попробуйте - и посмотрите, сколько информации вы сможете узнать!


Рейтинг:
1

Philippe Mori

ParameterGroup pg = parameterGroup
if  (!pg.ParametersGroups.TryGetValue(pgName, out pg))
{
      ParameterGroup newPg = new ParameterGroup();
      pg.ParametersGroups.Add(pgName, newPg);  // here pg is always null
}


В приведенном выше коде, pg всегда будет нулевым, так как когда что-то не найдено в словаре, то out параметр будет равен нулю.

Таким образом, этот код, очевидно, будет выдавать исключение каждый раз, когда нет группы параметров с указанным именем.

Очевидно, что вы не должны использовать одну и ту же переменную дважды, если вам все еще нужен исходный словарь.

Я не проверял остальную часть кода, но, учитывая эту ошибку, я бы рекомендовал вам прочитать документацию функции перед написанием кода.