C# 我怎样才能重新编写这段代码,使其看起来不象是在使用异常作为流控制的一种形式?

C# 我怎样才能重新编写这段代码,使其看起来不象是在使用异常作为流控制的一种形式?,c#,exception,control-flow,try-catch-finally,C#,Exception,Control Flow,Try Catch Finally,我听说异常和try-catch块不应该用于流控制,所以我想找到一种方法来重新编写代码以避免出现这种情况 我有一个方法validateTrainingSets,在一个neuralNetwork类中,它完全按照它的名字来做——验证提供的训练集(除其他外,确保训练集中的输入数量与神经网络的输入数量相匹配,每个答案的输出数量与神经网络的最终输出数量相匹配) 因为有许多不同的方式会导致验证失败,所以我决定将异常的抛出留给验证方法本身,并且有三种不同的自定义异常可以从函数中抛出 在允许类用户手动更新每层神经

我听说异常和try-catch块不应该用于流控制,所以我想找到一种方法来重新编写代码以避免出现这种情况

我有一个方法validateTrainingSets,在一个neuralNetwork类中,它完全按照它的名字来做——验证提供的训练集(除其他外,确保训练集中的输入数量与神经网络的输入数量相匹配,每个答案的输出数量与神经网络的最终输出数量相匹配)

因为有许多不同的方式会导致验证失败,所以我决定将异常的抛出留给验证方法本身,并且有三种不同的自定义异常可以从函数中抛出

在允许类用户手动更新每层神经元数量的方法中,最后一位代码验证和/或更新训练集(取决于是否提供了新的训练集),我的问题是,如何改进它

在下面的代码中,验证器中的“true”参数告诉验证器,如果失败,则将训练集设置为null。(如果用户没有提供新的训练集,但现有训练集与新的安排一致,则保留训练集,如果没有,则丢弃训练集)

fldValidate字段是一个在代码前面设置为false的标志,我需要确保它被设置为true,并且没有任何错误

try { validateTrainingSets(fldTrainingSets, fldTrainingAnswers, true); }
catch(TrainingSetCardinalityMismatch) { }
catch(InputSetCardinlityMismatch) { }
catch(OutputAnswerCardinalityMismatch) { }
catch {
    fldValidate = true;
    throw;
}
finally { fldValidate = true; }

是的,我认为大多数审阅者会发现这一点令人困惑,并要求进行更改。如果我正确理解了问题,您可以使用
enum
,例如:

enum Validity { Valid, TrainingSetCardinalityMismatch, InputSetCardinalityMismatch, OutputAnswerCardinalityMismatch } 

class TrainingSet { 
    Validity Validate(TrainingAnswer[] trainingAnswers) { // ... etc ... } 
}
var validTrainingSets = 
    from trainingSet in fldTrainingSets 
    where trainingSet.Validate(fldTrainingSets) == Validity.Valid
    select trainingSet;
然后按你觉得最直观的方式进行划分,例如:

enum Validity { Valid, TrainingSetCardinalityMismatch, InputSetCardinalityMismatch, OutputAnswerCardinalityMismatch } 

class TrainingSet { 
    Validity Validate(TrainingAnswer[] trainingAnswers) { // ... etc ... } 
}
var validTrainingSets = 
    from trainingSet in fldTrainingSets 
    where trainingSet.Validate(fldTrainingSets) == Validity.Valid
    select trainingSet;
或:

或:


是的,我认为大多数审阅者会发现这一点令人困惑,并要求进行更改。如果我正确理解了问题,您可以使用
enum
,例如:

enum Validity { Valid, TrainingSetCardinalityMismatch, InputSetCardinalityMismatch, OutputAnswerCardinalityMismatch } 

class TrainingSet { 
    Validity Validate(TrainingAnswer[] trainingAnswers) { // ... etc ... } 
}
var validTrainingSets = 
    from trainingSet in fldTrainingSets 
    where trainingSet.Validate(fldTrainingSets) == Validity.Valid
    select trainingSet;
然后按你觉得最直观的方式进行划分,例如:

enum Validity { Valid, TrainingSetCardinalityMismatch, InputSetCardinalityMismatch, OutputAnswerCardinalityMismatch } 

class TrainingSet { 
    Validity Validate(TrainingAnswer[] trainingAnswers) { // ... etc ... } 
}
var validTrainingSets = 
    from trainingSet in fldTrainingSets 
    where trainingSet.Validate(fldTrainingSets) == Validity.Valid
    select trainingSet;
或:

或:


catch{}
块是不必要的。通常,try/catch/throw应该用于“异常”情况,而不仅仅用于程序流控制。在您的情况下,另一种选择是让
validateTrainingSets
返回一个枚举类型,其中包含四个选项(成功、TrainingSetCardinalityMismatch等)。这是否会使您的代码更干净?这要看情况而定。需要认识到的一点是,抛出异常代价高昂(编写try/catch/finally很便宜,但实际抛出需要很长时间)。这可能会影响您的决定。在任何情况下,这都是“基于意见的”而且很可能会被关闭对于代码审查或软件工程SE站点来说,这可能是一个更好的问题。@Flydog57I重新编写了这个问题,以避免基于意见,并符合已经提供的一些建议。我读了很多关于天气与否的文章。例外情况应仅在“例外”中使用案例,&双方都有人。对我来说最有意义的解释是,如果一个功能的假设是不正确的,而不是返回一个任意值来表示,最好抛出一个异常,让其他人知道这个问题。当然是codereview.stackexchange.com,它是stackov的姐妹站点erflow是一个更好的地方,可以询问人们的思维定势。这里的“对”和“错”更少,更多的是“变得更好”。我今天在那里问了一个问题,对答案中的改进感到非常高兴。
catch{}
块是不必要的。一般来说,try/catch/throw应该用于“例外”环境,而不仅仅是程序流控制。在您的情况下,另一种选择是让
validateTrainingSets
返回一个带有四个选项的枚举类型(Successed、TrainingSetCardinalityMismatch等)。这是否会使您的代码更干净?这要看情况而定。需要认识到的一点是,抛出异常代价高昂(编写try/catch/finally很便宜,但实际抛出需要很长时间)。这可能会影响您的决定。在任何情况下,这都是“基于意见的”而且很可能会被关闭对于代码审查或软件工程SE站点来说,这可能是一个更好的问题。@Flydog57I重新编写了这个问题,以避免基于意见,并符合已经提供的一些建议。我读了很多关于天气与否的文章。例外情况应仅在“例外”中使用案例,&双方都有人。对我来说最有意义的解释是,如果一个功能的假设是不正确的,而不是返回一个任意值来表示,最好抛出一个异常,让其他人知道这个问题。当然是codereview.stackexchange.com,它是stackov的姐妹站点erflow是一个更好的地方,可以询问人们的思维定势。这里没有“对”和“错”,更多的是“做得更好”。我今天在那里问了一个问题,对答案的改进感到非常高兴。我喜欢这个想法,只是我还需要一种方法来传递其他参数,例如paramName、message、actualValue等。在我为特定异常创建的自定义字段中,可能会让它返回一个包含这些字段的结构枚举的字段?我已经编辑了答案,以包含返回接口或抽象类的可能性。实际上我更喜欢这个想法:创建表达类型是一个非常好的做法。有一个更复杂的路径称为
monad,它允许您自动拆分有效集和无效集,但这有点像兔子洞。哦,我看到你用抽象类解决了这个问题,我认为这实际上是完美的,谢谢!我喜欢这个想法,除了我还需要一种方法来通过其他段落