2017-04-20 111 views
0

我知道这个问题已经在网站上得到解决。虽然有很多不同的观点,但我想更深入地了解如何面对某些特定情况。 让我们说我有以下代码。我将用C#编写,但它不是严格相关的C#问题。如何处理非法参数验证

class Player 
{ 
    private int dexterity; 
    public int Dexterity{ 
     get => dexterity; 
     set{ 
      //Here I need to validate: problem 2 
      dexterity = value; 
      UpdateArmorClass(); //Armor class should be modified any time dex is 
     } 
    private int armorClass; 

    public Player(int dex){ 
     Dexterity = dex; 
    } 

    private void UpdateArmorClass(){ 
     //Should I validate here? Problem 3 
     armorClass = 10 + Dexterity; 
    } 
} 
//Here is main with user input: problem 1 

让我们说一个用户被要求输入其detxterity,必须为非负,创造它的性格。现在我面临三种情况:

  • 问题1:用户输入验证:读书的时候,我一直相信,我从来没有shuold使用异常验证用户输入,因为它的东西,比较常见的现象。我想我可以通过使用一个布尔型的isValid来解决这个问题,并且要求用户再次输入他的值,如果它是假的。这是一个好的解决方案吗?
  • 问题2:在构造函数中验证:好,这不是真的在构造函数中,我把它放在灵巧的制定者,这将是由构造被调用。先验的是,不需要检查这个,因为如果用户输入已经被验证,数据将是正确的。 虽然,我可以在代码中的其他地方创建播放器(所以我想检查程序员级别而不是用户级别),灵巧性也不允许为负数。在这里,我面临着这样一个巨大的困境:使用异常或不? 我亲自使用它们来阻止程序生成无效对象。尽管如此,许多人不鼓励使用异常,因为其价格昂贵。我能想到的唯一解决方案是在给定值错误时给出默认值。虽然,它似乎棘手的解决方案对我来说,因为该程序将继续前进,我不会知道默认值已被放置(这可能是错误的我的情况)。所以,真正的问题是:我是否应该使用异常来处理结构函数(或setter)中的这种情况?
  • 问题3:方法验证:现在我知道也不应该允许armorClass为负数。在我的情况下,我有一个私人方法,可以随时更新armorclass,随时灵活性被修改。所以真的不需要在这里再次验证。现在假设我制作了另一个用于进行简单对战的课程,并在本帖末尾显示了计算方法,该方法计算被击中的概率。它期望获得一些armorClass值,尽管我可能是另一个程序员,并且不知道Player中的armorClass是否已经被验证。所以我检查它是否是非负面的。抛出这样一个检查异常似乎很多,但如果我检查它的非负面性,我必须返回一个默认值,当armorClass为负时,这似乎很棘手。 在这种情况下我该怎么办?

这里的最后一个方法:

public float Hit(int armorClass){ 
    if(armorClass >=0) //calculate probability of being hit 
    //return probability 
} 

奖金问题(相关课程的前面的问题):被实例化一个新的异常真的那么贵吗?或者它只是尝试捕捉部分?对我来说,它似乎是实例化一个新的对象,就这些。虽然,我可能是错的,这就是为什么很多人说你不应该使用例外,如果不是真的需要。

+0

不相关的问题:在二传手,'敏捷=灵巧;'应该是'灵巧敏捷=;' –

+0

呀,实际上是是一个错字。我在C#中使用'dexterity = value',但是我认为结果和你写的一样。 – Harnak

+0

当然,'灵巧=值':我的错字! –

回答

2

在这里,我所面临的大难题:使用异常或没有?我倒是 亲自用它从产生无效 对象停止程序。尽管如此,许多人不愿意使用异常,因为其价格昂贵。

使用异常。异常只在引发时才是昂贵的,并且最好引发异常而不是结束损坏的对象。如果您的值来自用户输入,则分别处理从用户获取它的无效值。这样,您可以安全地从代码中调用这些方法/设置值,并且在用户输入无效值时不会引发异常。另外,有时您可能希望允许使用的特殊值,不应该允许用户输入。

问题3: 如果你的私有字段设置之前,请务必确认,存在如果有效上获取检查是没有意义的。在您的代码示例中,向任何非负数添加10将始终返回非负值。

红利问题: 所有引发的异常都必须在某个地方处理,所以我不认为如果它的引发异常部分是昂贵的或捕获部分,那么我不认为这很重要。

+0

非常感谢您的明确回答!最后一个例子(在另一个类中使用公共方法)呢?你会在那里检查装甲班吗?就像,如果armor类是积极的:计算概率;否则,什么都不做/返回默认值(例如0)。我总是很难想象这种验证的后果。尽管如此,这似乎是唯一的解决方案。 – Harnak

+0

嗯,这是一个公开的方法,所以假设你的参数总是有效的可能不是最好的办法。当涉及到要做什么,它取决于逻辑。如果在某些情况下,你的“armorClass”可能是性否定(如IE。一些敌人修改器把所有的盔甲就像是1级以下)和返回0是有效的,期望值这种方法,返回它是完全正常的。如果'armorClass'不应该是负数,那么抛出一个异常或使用'Debug.Assert'即可。你可以使用最新的不会在生产中崩溃你的应用程序,但清楚地看到我调试错了。 –

+0

感谢您的所有建议。这真的很有用:-) – Harnak