为什么当只传递一个字符串数组时,编译器会因为一个非常量表达式而出错?

问题描述 投票:0回答:1

当我把一个字符串数组传给这样的测试函数时。

[TestCase( new string[] { "1", "2", "3" }, 1 )]
[TestCase( new string[] { "54", "508" }, 1 )]
[TestCase( new string[] { "768" }, 2 )]
public void someTest( string[] someStrings, int someNumber ) {
    //...
}

编译工作正常。

但是,如果我删除整数参数,就像下面的代码片段所示。

[TestCase( new string[] { "1", "2", "3" } )]
[TestCase( new string[] { "54", "508" } )]
[TestCase( new string[] { "768" } )]
public void someTest( string[] someStrings ) {
    //...
}

编译器出错,并显示 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type 发生。

我基本上知道了错误的原因,数组不是常量类型。但是,如果有其他参数传递给测试函数,为什么编译器会接受一个数组呢?如果我把另一个数组放在TestCase里面,它甚至可以工作。

[TestCase( new string[] { "1", "2", "3" }, new int[] { 1, 2, 3 } )]
[TestCase( new string[] { "54", "508" }, new int[] { 54, 508 } )]
[TestCase( new string[] { "768" }, new int[] { 768 } )]
public void someTest( string[] someStrings, int[] someNumbers ) {
    //...
}
c# visual-studio-2013 nunit
1个回答
2
投票

让我们把它简化为不涉及重载的东西,同时也删除了 params:

using System;

[AttributeUsage(AttributeTargets.All)]
class FooAttribute : Attribute
{
    public FooAttribute(object[] args)
    {
    }
}

// Error
[Foo(new string[] { "a", "b" })]
class FooTest1 {}

// Error
[Foo(new[] { "a", "b" })]
class FooTest2 {}

// Error
[Foo(args: new string[] { "a", "b" })]
class FooTest3 {}

// Error
[Foo((object[]) new string[] { "a", "b" })]
class FooTest4 {}

// Works
[Foo(new object[] { "a", "b" })]
class FooTest5 {}

// Works
[Foo(new[] { (object) "a", "b" })]
class FooTest6 {}

基本上,编译器不愿意提供一个 string[] 对于 object[] 属性中的参数,尽管通常情况下这是没有问题的。

I 相信 这是一个编译器的错误,我检查了规范--但我不想确定。表达式 new string[] { "a", "b" } 算是 属性参数表达式 在规格方面--如果你把参数类型改为 string[] 它工作得很好。所以问题就出在参数的参数类型的应用上。规范还说,属性参数和参数 "受到与简单赋值相同的规则的约束"--但在这种情况下是可以的。所以我在规范中看不到任何应该不允许这样做的地方。


0
投票

看起来像是一个重载问题。

TestCaseAttribute 有以下构造函数。

TestCaseAttribute(object arg);                             // A
TestCaseAttribute(object arg1, object arg2);               // B
TestCaseAttribute(object arg1, object agr2, object arg3);  // C
TestCaseAttribute(params object[] arguments);              // D

你的第一个例子和你的第三个例子都符合(B)。

你想让第二个(失败的那个)匹配(A),但实际上它是匹配(D)

尝试将数组转换为一个对象

[TestCase( (object) new string[] { "1", "2", "3" } )]

或使用命名参数传递

[TestCase( arg: new string[] { "1", "2", "3" } )]

属性规则允许传递一维数组,但二维数组(如描述的 此处),所以(D)不允许用数组。

© www.soinside.com 2019 - 2024. All rights reserved.