为什么编译器在仅传递字符串数组时会因为非常量表达式而出错
Why is the compiler giving an error because of a non constant expression when passing just a string array
当我像这样将字符串数组传递给测试函数时:
[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 ) {
//...
}
看起来像是一个过载问题。
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" } )]
属性的规则允许传递一维数组,但不能传递二维数组(如here所述),所以(D)不允许带数组。
让我们将其简化为不涉及重载的内容,并删除 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 {}
基本上,编译器不愿意为属性中的 object[]
参数提供 string[]
,即使这通常没问题。
我相信这是一个编译器错误,已经检查了规范 - 但我不想肯定地说。表达式 new string[] { "a", "b" }
在规范方面确实算作 属性参数表达式 - 如果将参数类型更改为 string[]
它可以正常工作。因此,问题在于将该参数类型应用于参数。规范还说属性参数和参数是 "are constrained by the same rules as simple assignment" - 但在这种情况下没问题。所以我在规范中看不到任何禁止这样做的内容。
当我像这样将字符串数组传递给测试函数时:
[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 ) {
//...
}
看起来像是一个过载问题。
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" } )]
属性的规则允许传递一维数组,但不能传递二维数组(如here所述),所以(D)不允许带数组。
让我们将其简化为不涉及重载的内容,并删除 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 {}
基本上,编译器不愿意为属性中的 object[]
参数提供 string[]
,即使这通常没问题。
我相信这是一个编译器错误,已经检查了规范 - 但我不想肯定地说。表达式 new string[] { "a", "b" }
在规范方面确实算作 属性参数表达式 - 如果将参数类型更改为 string[]
它可以正常工作。因此,问题在于将该参数类型应用于参数。规范还说属性参数和参数是 "are constrained by the same rules as simple assignment" - 但在这种情况下没问题。所以我在规范中看不到任何禁止这样做的内容。