C# NUnit 3.0 TestCase常量自定义对象参数

C# NUnit 3.0 TestCase常量自定义对象参数,c#,nunit,C#,Nunit,我已经编写了类SomeObject,我想定义这个对象的const实例,以便在我的TestCases中保留/重用。我应该如何重写下面的代码来实现这种行为 [TestFixture] public class SomeObjectTests { private const SomeObject item0 = new SomeObject(0.0); // doesn't work [TestCase(item0, ExpectedResult = 0.0)] public

我已经编写了类
SomeObject
,我想定义这个对象的
const
实例,以便在我的
TestCase
s中保留/重用。我应该如何重写下面的代码来实现这种行为

[TestFixture]
public class SomeObjectTests
{
    private const SomeObject item0 = new SomeObject(0.0); // doesn't work

    [TestCase(item0, ExpectedResult = 0.0)]
    public double TestSomeObjectValue(SomeObject so)
    {
        return so.Value;
    }

    [TestCase(item0, ExpectedResult = "0.0")]
    public string TestSomeObjectValueString(SomeObject so)
    {
        return so.ValueString;
    }
}
我收到以下错误消息:

引用类型不是字符串的常量字段只能用null初始化

(我的)重点说:

如果需要常量值的符号名,但常量声明中不允许该值的类型,或者无法在编译时通过常量表达式计算该值,则可以使用只读
字段()


令人烦恼的是,属性也有某些限制,这一事实使情况更加复杂-请参见(再次强调我的):

如果以下所有语句均为真,则表达式E为属性参数表达式:

  • E的类型为属性参数类型(第17.1.3节)

  • 在编译时,E的值可以解析为以下值之一:

    • 一个常量。

    • 一个System.Type对象

    • 属性参数表达式的一维数组

其中:“属性参数类型”表示1:

属性类的位置参数和命名参数的类型仅限于属性参数类型,即:

  • 以下类型之一:
    bool
    byte
    char
    double
    float
    int
    long
    short
    string
  • 类型
    对象
  • 类型
    System.type
  • 枚举类型,前提是它具有公共可访问性,并且嵌套它的类型(如果有)也具有公共可访问性(§17.2)
  • 上述类型的一维数组
1:引用的文本来自C规范的旧版本-在该版本中,提到了四种附加类型:
sbyte
uint
ulong
,和
ushort


换句话说,你能做的最好的事情是:

[TestFixture]
public class SomeObjectTests {

    private static readonly SomeObject item0 = new SomeObject(0.0);

    private static SomeObject getObject(string key) {
        if ( key == "item0" )
            return item0;

        throw new ArgumentException("Unknown key");
    }

    [TestCase("item0", ExpectedResult = 0.0)]
    public double TestSomeObjectValue(string key) {
        SomeObject so = getObject(key);
        return so.Value;
    }

    [TestCase("item0", ExpectedResult = "0.0")]
    public string TestSomeObjectValueString(string key) {
        SomeObject so = getObject(key);
        return so.ValueString;
    }
}
这样,属性的参数是编译时常量,
getObject
方法可以处理获取
SomeObject
实例

  • 只要去掉常数。它将是每个实例的私有变量
  • 使它成为静态的,它将成为类的单例
  • 将常量替换为只读。这将标志着这是一件不应该被弄乱的事情

  • 实现你想要做的事情的一个更好的方法是使用。就你而言:

    [TestFixture]
    public class SomeObjectTests
    {
        [TestCaseSource(typeof(TestSomeObject),"TestCasesValue")]
        public double TestSomeObjectValue(SomeObject so)
        {
            return so.Value;
        }
    
        [TestCaseSource(typeof(TestSomeObject),"TestCasesValueString")]
        public string TestSomeObjectValueString(SomeObject so)
        {
            return so.ValueString;
        }
    }
    
    public class TestSomeObject
    {
      public static IEnumerable TestCasesValue
      {
        get
        {
            yield return new TestCaseData( new SomeObject(0.0) ).Returns( 0.0 );
            yield return new TestCaseData( new SomeObject(1.0) ).Returns( 1.0 );
        }
      }
    
      public static IEnumerable TestCasesValueString
      {
        get
        {
            yield return new TestCaseData( new SomeObject(0.0) ).Returns( "0.0" );
            yield return new TestCaseData( new SomeObject(1.0) ).Returns( "1.0" );
        }
      }
    }
    

    从代码中删除
    const
    ,它只是静态的,不会保持不变。请使用
    static readonly
    而不是
    const
    。c#不支持所有类型的const。类型必须是编译时常量。请参见此处编辑:添加了我收到的错误消息。是我对NUnit的问题,还是我在C中遗漏了一些基本的东西?这是C中的一些基本的东西。对象引用不能是编译时常量,因此不符合
    const
    string
    是一个例外,但是。@M.kazemAkhgary您可以对任何类型使用
    const
    。每个类型都至少有一个该类型的编译时常量文本。大多数类型无法创建任何有用的
    const
    值,因为该类型的大多数有意义的值都没有编译时文本。我得到错误消息:
    属性参数必须是常量表达式、typeof表达式或属性参数类型的数组创建表达式
    Hmm-我只回答了你一半的问题。请给我一点时间更新我的答案(我在手机上)。@WaiHaLee您可以使用编译时文本
    default(thetypeofvariablegoesher)
    创建任何有效C类型(值或引用类型)的
    const
    标识符。您还可以使用
    typeof
    创建
    type
    类型的编译时常量值。重新阅读后,我发现这句话实际上在技术上是正确的,这是我的错误,但你的结论并非如此。即使您不能为大多数类型创建合理的值,您仍然可以为这些类型创建
    const
    标识符,并至少为其分配一个有效值。@JeppeStigNielsen-进一步调查,您是对的。语言规范(C#5.0中的10.4)规定:常量声明中指定的类型必须是
    sbyte
    byte
    short
    ushort
    int
    uint
    long
    ulong
    char
    float
    double
    十进制
    字符串
    enum
    -类型或引用类型。每个常量表达式必须产生一个目标类型的值或一个可以通过隐式转换转换为目标类型的类型的值”同样,表示:“属性类的位置参数和命名参数的类型仅限于属性参数类型,即:(a)以下类型之一:
    bool
    byte
    char
    double
    float
    int
    long
    short
    string
    ,(b)类型
    对象
    ,(c)类型
    系统类型
    ,(d)枚举类型,前提是它具有公共可访问性和嵌套的类型(如果有的话)还具有公共可访问性(§17.2),(e)上述类型的一维数组。”。TestCaseData是描述数据的一种方法,以及您希望对数据执行的操作。通常,您可以返回一些对象d