.net有条件不正确评估

时间:2011-04-12 22:13:20

标签: .net conditional try-catch throw

我有以下简单的代码块

  var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
  if (!File.Exists(assmSpec))
      throw new TaskException(string.Format(
          "Assembly [{0}] cannot be located.", assmSpec));

由于assmSpec引用的程序集确实存在(File.Exists() evals为true),我希望异常将抛出。但它是。代码步入throw语句。为了调试,我将代码修改为:

  var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
  var asmExists = File.Exists(assmSpec);
  if (!asmExists)
      throw new TaskException(string.Format(
          "Assembly [{0}] cannot be located.", assmSpec));

在这里,asmExists逐渐变为真,而且代码仍然进入了抛出。

然后我将代码修改为:

  var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName; // evals to valid fileSpec
  if (!File.Exists(assmSpec) && File.Exists(assmSpec))
      throw new TaskException(string.Format(
         "Assembly [{0}] cannot be located.", assmSpec));

再次,代码仍然命中。这里显然是非常错误的。有人有解释吗?我在这里做的事真的很愚蠢吗?

fwiw,这个代码在一个方法中也有一个try - catch - finally构造,但它在所有这些之前(在尝试之前)......


完整的方法是:

  public void StartProcess(Task task)
    {
        log.Write(log.Level.Debug, string.Format(
            "TaskWorker.StartProcess {0} process",
            task.Name), task.Name);
        WorkerMessageManager.MsgArrvdWorkerHndlr += MsgArrvdWorkerHndlr;
        var tskName = task.Name;
        var assmSpec = util.ASSEMBLYFOLDER + task.AssemblyName;
        if (!File.Exists(assmSpec))
            throw new TaskException(string.Format(
                "Assembly [{0}] cannot be located.", assmSpec));

        try
        {
            WorkerMessageManager.NotifyWorker(new ProgressTaskMessage(
                                    tskName, "", tskName + "  starting..."));
            // -------------------------------------------
            Assembly dA;
            try { dA = Assembly.LoadFrom(assmSpec); }
            catch(FileNotFoundException nfX)
            { throw new TaskException(string.Format(
                "Assembly [{0}] cannot be located.", assmSpec), 
                nfX); }
            // -------------------------------------------
            var iTsk = (IExecuteTasks)dA.CreateInstance(task.ClassName);
            if (iTsk == null)
                throw new TaskException(
                    string.Format("Unable to instantiate {0} from {1}",
                        task.ClassName, task.AssemblyName));

            if (iTsk.TaskName != tskName) // do not execute if names do not match
                throw new TaskNameMismatchException(string.Format(
                    "CHECK CONFIGURATION SETTINGS,  Data Task Name Mismatch.{0}" +
                    "Task name defined in TaskScheduler.config [{1}], {0} does " +
                    "not match name [{2}] as defined in Task Logic assembly: {3}.{4}",
                        sNL, tskName, iTsk.TaskName, task.AssemblyName, 
                        task.ClassName),  tskName, iTsk.TaskName);
            // -------------------------------------------
            iTsk.DataImportProgressEvent += OnProgressReport;
            iTsk.ProcessCompletedEvent += OnProcessCompleted;
            iTsk.GeneralEvent += OnGeneralEvent;
            // -----------------------------------
            log.Write(log.Level.Debug, string.Format(
                  "{0} process Started", task.Name),
                  task.Name);
            if (task.JobQueue.HasJobReady)
                iTsk.StartTask(JobQueues.Instance.DeQueue(tskName));
            else iTsk.StartTask(); 
            log.Write(log.Level.Debug, string.Format(
                  "{0} process Completed", task.Name),
                  task.Name);
        }
        catch (TaskNameMismatchException inmX)
        { log.Write(log.Level.Warn, inmX.Message, tskName, inmX); }

        catch (BpaTaskException mX)
        {
            var errMsg = string.Format(
                "Error in Data Import StartProcess(). " + sNL +
                "Exception {0}: {1}, " + sNL +
                "Stack Trace: {2}",
                mX, mX.Message, mX.StackTrace); 
            log.Write(log.Level.Error, errMsg, 
                        task.Name, mX);
        }

        catch(Exception X)
        {
            var errMsg = string.Format(
                "Error in Data Import StartProcess(). " + sNL +
                "Exception {0}: {1}, " + sNL +
                "Stack Trace: {2}",
                X, X.Message, X.StackTrace);
            log.Write(log.Level.Error, errMsg, task.Name, X);

            // WorkerMessageManager.NotifyWorker(new ImportFailMessage(X));
            // This throw instruction causes the Scheduler service to stop alltogether
            // I'm Removing the throw for now, because it seems inappropriate to 
            //          kill the whole service..
            throw;
        }

        finally
        {
            task.IsRunning = false;
            WorkerMessageManager.MsgArrvdWorkerHndlr -= MsgArrvdWorkerHndlr;
        }
    }

3 个答案:

答案 0 :(得分:2)

检查同一行上的if ()语句后面是否有文本(代码或分号)。最可能的原因是“throw”实际上并不是if语句的“内部”,所以它总是被执行。

检查您是否正在调试DEBUG构建 - 您可能会在调试器中为RELEASE构建报告奇数值,这可能使得它看起来好像变量为true,而实际上它是假的。

在某些情况下(尽管通常仅提供对预编译dll或损坏的pdb文件的引用)也可以查看与调试不同的代码,从而给人的印象是,您对源代码所做的更改将被忽略。做一个Build>清理,检查您正在运行的程序集是否已不再存在于磁盘上,然后重新构建它以确保它是最新的并与源代码同步。

答案 1 :(得分:0)

我刚试过类似的东西,它对我来说很好。您是否尝试使用语句块而不是单个抛出线?

编译器可能会混淆,可能需要重新启动。这不是闻所未闻的。 :/

答案 2 :(得分:0)

如果你看一下File.Exists方法的内部,你会发现它会在很多情况下返回false,包括:

  1. path为null或空字符串
  2. 该文件不存在
  3. 操作系统认为该文件实际上是一个目录
  4. 尝试访问该文件的帐户没有读取权限。
  5. 抛出一些其他内部NotSupportedException,SecurityException,IOException或UnauthorizedAccessException。
  6. 问题是所有这些潜在的错误都被埋没了。我建议改为尝试FileInfo课程:

    var fileInfo = new FileInfo( assmSpec );
    if ( !fileInfo.Exists )
        throw new TaskException( ...
    

    FileInfo上的构造函数会向您返回一些异常中的一个,这可能会为您提供有关该问题的更多信息。