System.String 构造函数
本文提供了此 API 参考文档的补充说明。
重载构造函数语法
字符串构造函数分为两个类别:那些没有指针参数的构造函数,以及那些具有指针参数的构造函数 。 使用指针的构造函数不符合 CLS。 此外,Visual Basic 不支持使用指针,C# 需要使用指针在不安全的上下文中运行的代码。 有关详细信息,请参阅 unsafe。
有关选择重载的其他指导,请参阅我调用哪种方法?
String(Char[] value)
将新实例初始化为 Unicode 字符数组指示的值。 此构造函数复制 Unicode 字符(示例 2:使用字符数组)。
String(Char[] value, Int32 startIndex, Int32 length)
将新实例初始化为 Unicode 字符数组、该数组中的起始字符位置和长度(示例 3:使用字符数组的一部分并重复单个字符)指示的值。
String(Char c, Int32 count)
将新实例初始化为指定的 Unicode 字符所指示的值重复指定的次数(示例 3:使用字符数组的一部分并重复单个字符)。
String(char* value)
(不符合 CLS) 将新实例初始化为指向 Unicode 字符数组(U+0000 或“\0”)终止的 Unicode 字符数组指示的值。 (示例 4:使用指向字符数组的指针)。
权限: SecurityCriticalAttribute要求立即调用方完全信任。 此成员不能由部分受信任或透明代码使用。
String(char* value, Int32 startIndex, Int32 length)
(不符合 CLS) 将新实例初始化为指向 Unicode 字符数组的指针、该数组中的起始字符位置以及长度指示的值。 构造函数从value
索引startIndex
处开始复制 Unicode 字符并以索引length
+ startIndex
结尾 - 1(示例 5:实例化指针中的字符串和数组范围)。
权限: SecurityCriticalAttribute要求立即调用方完全信任。 此成员不能由部分受信任或透明代码使用。
String(SByte* value)
(不符合 CLS) 将新实例初始化为指向 8 位带符号整数数组的指针指示的值。 假定该数组表示使用当前系统代码页(即指定的编码)编码的 Encoding.Default字符串。 构造函数从指针指定的位置开始处理字符 value
,直到到达 null 字符(0x00)(示例 6:实例化指向带符号字节数组的指针中的字符串)。
权限: SecurityCriticalAttribute要求立即调用方完全信任。 此成员不能由部分受信任或透明代码使用。
String(SByte* value, Int32 startIndex, Int32 length)
(不符合 CLS) 将新实例初始化为指向 8 位有符号整数数组、该数组中的起始位置以及长度的指针指示的值。 假定该数组表示使用当前系统代码页(即指定的编码)编码的 Encoding.Default字符串。 构造函数处理从值开始startIndex
到结尾startIndex
length
+ 的字符 - 1(示例 6:实例化指向带符号字节数组的指针中的字符串)。
权限: SecurityCriticalAttribute要求立即调用方完全信任。 此成员不能由部分受信任或透明代码使用。
String(SByte* value, Int32 startIndex, Int32 length, Encoding enc)
(不符合 CLS) 将新实例初始化为指向 8 位带符号整数数组的指针指示的值、该数组中的起始位置、长度和对象 Encoding 。
权限: SecurityCriticalAttribute要求立即调用方完全信任。 此成员不能由部分受信任或透明代码使用。
参数
下面是不包含指针参数的构造函数使用 String 的参数的完整列表。 有关每个重载使用的参数,请参阅上面的重载语法。
参数 | 类型 | 描述 |
---|---|---|
value |
Char[] | Unicode 字符的数组。 |
c |
Char | 一个 Unicode 字符。 |
startIndex |
Int32 | 新字符串中第一个字符的起始位置 value 。默认值:0 |
length |
Int32 | 要包含在新字符串中的字符 value 数。默认值:30Array.Length |
count |
Int32 | 新字符串中重复字符 c 的次数。 如果 count 为零,则新对象的 String.Empty值为 。 |
下面是包含指针参数的构造函数使用 String 的参数的完整列表。 有关每个重载使用的参数,请参阅上面的重载语法。
参数 | 类型 | 描述 |
---|---|---|
value |
Char* -或- SByte* |
指向以 null 结尾的 Unicode 字符数组或 8 位带符号整数数组的指针。 如果 value 为 null 或空数组,则新字符串的值为 String.Empty。 |
startIndex |
Int32 | 定义新字符串中第一个字符的数组元素的索引。 默认值:0 |
length |
Int32 | 用于创建新字符串的数组元素数。 如果长度为零,构造函数将创建一个值为 String.Empty 的字符串。 默认值:30Array.Length |
enc |
Encoding | 一个对象,指定数组的编码方式 value 。默认值: Encoding.Default或系统的当前 ANSI 代码页 |
异常
下面是不包含指针参数的构造函数引发的异常列表。
Exception | 条件 | 引发者 |
---|---|---|
ArgumentNullException | value 为 null 。 |
String(Char[], Int32, Int32) |
ArgumentOutOfRangeException | startIndex ,length 或 count 小于零。-或- startIndex 与 length 的和大于 value 中的元素数。-或- count 小于零。 |
String(Char, Int32) String(Char[], Int32, Int32) |
下面是包含指针参数的构造函数引发的异常列表。
Exception | 条件 | 引发者 |
---|---|---|
ArgumentException | value 指定包含无效 Unicode 字符的数组。-或- value 或 value + startIndex 指定小于 64K 的地址。-或- 无法从 value 字节数组初始化新String实例,因为value 不使用默认代码页编码。 |
所有具有指针的构造函数。 |
ArgumentNullException | value 为 null。 |
String(SByte*) String(SByte*, Int32, Int32) String(SByte*, Int32, Int32, Encoding) |
ArgumentOutOfRangeException | 当前进程不具有对所有通过地址访问的字符的读取访问权限。 -或- startIndex 或 length 小于零,value + startIndex 导致指针溢出,或者当前进程不具有对所有寻址字符的读取访问权限。-或- 新字符串的长度太大,无法分配。 |
所有具有指针的构造函数。 |
AccessViolationException | value 或 value + + startIndex length - 1,指定无效地址。 |
String(SByte*) String(SByte*, Int32, Int32) String(SByte*, Int32, Int32, Encoding) |
我调用哪种方法?
若要 | 呼叫或使用 |
---|---|
创建字符串。 | 来自字符串文本或现有字符串的赋值(示例 1:使用字符串赋值) |
从整个字符数组创建字符串。 | String(Char[]) (示例 2:使用字符数组) |
从字符数组的一部分创建字符串。 | String(Char[], Int32, Int32) (示例 3:使用字符数组的一部分并重复单个字符) |
创建多次重复同一个字符的字符串。 | String(Char, Int32) (示例 3:使用字符数组的一部分并重复单个字符) |
从指向 Unicode 或宽字符数组的指针创建字符串。 | String(Char*) |
使用其指针从 Unicode 或宽字符数组的一部分创建字符串。 | String(Char*, Int32, Int32) |
从 C++ char 数组创建字符串。 |
String(SByte*), String(SByte*, Int32, Int32) -或- String(SByte*, Int32, Int32, Encoding) |
从 ASCII 字符创建字符串。 | ASCIIEncoding.GetString |
创建字符串
以编程方式创建字符串的最常用方法是简单的赋值,如示例 1 所示。 该 String 类还包括四种类型的构造函数重载,可用于从以下值创建字符串:
从字符数组(UTF-16 编码字符数组)。 可以从整个数组或其中一部分的字符创建新 String 对象。 构造 String(Char[]) 函数将数组中的所有字符复制到新字符串。 构造 String(Char[], Int32, Int32) 函数将字符从索引复制到索引
startIndex
startIndex
+length
- 1 复制到新字符串。 如果length
为零,则新字符串的值为 String.Empty.如果代码重复实例化具有相同值的字符串,则可以使用创建字符串的替代方式来提高应用程序性能。 有关详细信息,请参阅 “处理重复字符串”。
使用构造函数从重复零、一次或多次的单个字符。String(Char, Int32) 如果
count
为零,则新字符串的值为 String.Empty.使用或String(Char*, Int32, Int32)构造函数,从指向以 null 结尾的字符数组的String(Char*)指针。 整个数组或指定的范围都可用于初始化字符串。 构造函数从指定指针或指定指针开始复制 Unicode 字符序列,然后
startIndex
继续到数组末尾或字符length
。 如果value
为 null 指针或length
零,则构造函数将创建一个值为 String.Empty 的字符串。 如果复制操作继续到数组的末尾,并且数组未以 null 结尾,则构造函数行为依赖于系统。 此类条件可能会导致访问冲突。如果数组包含任何嵌入的 null 字符(U+0000 或“\0”),并且 String(Char*, Int32, Int32) 调用重载,则字符串实例包含
length
包括任何嵌入的 null 字符。 以下示例演示当指向包含两个空字符的 10 个元素数组的指针传递给 String(Char*, Int32, Int32) 该方法时会发生什么情况。 由于地址是数组的开头,并且数组中的所有元素都将被添加到字符串中,因此构造函数将实例化一个包含十个字符的字符串,包括两个嵌入的 null。 另一方面,如果将同一数组传递给 String(Char*) 构造函数,则结果是一个不包含第一个 null 字符的四个字符字符串。using System; public class Example2 { public unsafe static void Main() { char[] chars = { 'a', 'b', 'c', 'd', '\0', 'A', 'B', 'C', 'D', '\0' }; string s = null; fixed(char* chPtr = chars) { s = new string(chPtr, 0, chars.Length); } foreach (var ch in s) Console.Write($"{(ushort)ch:X4} "); Console.WriteLine(); fixed(char* chPtr = chars) { s = new string(chPtr); } foreach (var ch in s) Console.Write($"{(ushort)ch:X4} "); Console.WriteLine(); } } // The example displays the following output: // 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 // 0061 0062 0063 0064
#nowarn "9" open System let chars = [| 'a'; 'b'; 'c'; 'd'; '\000'; 'A'; 'B'; 'C'; 'D'; '\000' |] let s = use chPtr = fixed chars String(chPtr, 0, chars.Length) for ch in s do printf $"{uint16 ch:X4} " printfn "" let s2 = use chPtr = fixed chars String chPtr for ch in s2 do printf $"{uint16 ch:X4} " printfn "" // The example displays the following output: // 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 // 0061 0062 0063 0064
数组必须包含 Unicode 字符。 在 C++ 中,这意味着字符数组必须定义为托管 Char[] 类型或非托管
wchar_t
类型。String(Char*)如果调用重载并且数组不是以 null 结尾的,或者String(Char*, Int32, Int32)调用重载且
startIndex
+length
-1 包含为字符序列分配的内存之外的范围,则构造函数的行为依赖于系统,并且可能会出现访问冲突。从指向有符号字节数组的指针。 整个数组或指定的范围都可用于初始化字符串。 可以使用默认代码页编码来解释字节序列,也可以在构造函数调用中指定编码。 如果构造函数尝试实例化不是以 null 结尾的整个数组中的字符串,或者数组范围从
value
startIndex
startIndex
length
+value
+ + -1 超出为数组分配的内存之外,则此构造函数的行为依赖于系统,并且可能会发生访问冲突。将带符号字节数组作为参数的三个构造函数主要用于将 C++
char
数组转换为字符串,如以下示例所示:using namespace System; void main() { char chars[] = { 'a', 'b', 'c', 'd', '\x00' }; char* charPtr = chars; String^ value = gcnew String(charPtr); Console::WriteLine(value); } // The example displays the following output: // abcd
如果数组包含任何 null 字符('\0')或其值为 0 且 String(SByte*, Int32, Int32) 调用重载的字节,则字符串实例将
length
包含包括任何嵌入 null 的字符。 以下示例演示当指向包含两个空字符的 10 个元素数组的指针传递给 String(SByte*, Int32, Int32) 该方法时会发生什么情况。 由于地址是数组的开头,并且数组中的所有元素都将被添加到字符串中,因此构造函数将实例化一个包含十个字符的字符串,包括两个嵌入的 null。 另一方面,如果将同一数组传递给 String(SByte*) 构造函数,则结果是一个不包含第一个 null 字符的四个字符字符串。using System; public class Example5 { public unsafe static void Main() { sbyte[] bytes = { 0x61, 0x62, 0x063, 0x064, 0x00, 0x41, 0x42, 0x43, 0x44, 0x00 }; string s = null; fixed (sbyte* bytePtr = bytes) { s = new string(bytePtr, 0, bytes.Length); } foreach (var ch in s) Console.Write($"{(ushort)ch:X4} "); Console.WriteLine(); fixed(sbyte* bytePtr = bytes) { s = new string(bytePtr); } foreach (var ch in s) Console.Write($"{(ushort)ch:X4} "); Console.WriteLine(); } } // The example displays the following output: // 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 // 0061 0062 0063 0064
#nowarn "9" open System let bytes = [| 0x61y; 0x62y; 0x063y; 0x064y; 0x00y; 0x41y; 0x42y; 0x43y; 0x44y; 0x00y |] let s = use bytePtr = fixed bytes String(bytePtr, 0, bytes.Length) for ch in s do printf $"{uint16 ch:X4} " printfn "" let s2 = use bytePtr = fixed bytes String bytePtr for ch in s do printf $"{uint16 ch:X4} " printfn "" // The example displays the following output: // 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 // 0061 0062 0063 0064
String(SByte*)由于构造String(SByte*, Int32, Int32)函数使用默认的 ANSI 代码页进行解释
value
,因此调用具有相同字节数组的构造函数可能会创建在不同系统上具有不同值的字符串。
处理重复字符串
分析或解码文本流的应用通常使用 String(Char[], Int32, Int32) 构造函数或 StringBuilder.Append(Char[], Int32, Int32) 方法将字符序列转换为字符串。 重复创建具有相同值的新字符串,而不是创建和重复使用一个字符串会浪费内存。 如果可能通过调用 String(Char[], Int32, Int32) 构造函数重复创建相同的字符串值,即使事先不知道这些相同的字符串值是什么,也可以改用查阅表格。
例如,假设从包含 XML 标记和属性的文件读取和分析字符流。 分析流时,会反复遇到某些标记(即具有符号意义的字符序列)。 等效于字符串“0”、“1”、“true”和“false”的标记很可能经常出现在 XML 流中。
可以创建一个 System.Xml.NameTable 对象来保存常见字符串,而不是将每个令牌转换为新字符串。 对象 NameTable 可提高性能,因为它检索存储的字符串而不分配临时内存。 遇到令牌时,请使用 NameTable.Get(Char[], Int32, Int32) 该方法从表中检索令牌。 如果令牌存在,该方法将返回相应的字符串。 如果该令牌不存在,请使用 NameTable.Add(Char[], Int32, Int32) 该方法将令牌插入表中并获取相应的字符串。
示例 1:使用字符串分配
以下示例通过为其分配字符串文本来创建一个新字符串。 它通过将第一个字符串的值分配给第二个字符串来创建第二个字符串。 这是实例化新 String 对象的两种最常见方法。
using System;
public class Example3
{
public static void Main()
{
String value1 = "This is a string.";
String value2 = value1;
Console.WriteLine(value1);
Console.WriteLine(value2);
}
}
// The example displays the following output:
// This is a string.
// This is a string.
let value1 = "This is a string."
let value2 = value1
printfn "%s" value1
printfn "%s" value2
// The example displays the following output:
// This is a string.
// This is a string.
Module Example
Public Sub Main()
Dim value1 As String = "This is a string."
Dim value2 As String = value1
Console.WriteLine(value1)
Console.WriteLine(value2)
End Sub
End Module
' The example displays the following output:
' This is a string.
' This is a string.
示例 2:使用字符数组
以下示例演示如何从字符数组创建新 String 对象。
// Unicode Mathematical operators
char [] charArr1 = {'\u2200','\u2202','\u200F','\u2205'};
String szMathSymbols = new String(charArr1);
// Unicode Letterlike Symbols
char [] charArr2 = {'\u2111','\u2118','\u2122','\u2126'};
String szLetterLike = new String (charArr2);
// Compare Strings - the result is false
Console.WriteLine("The Strings are equal? " +
(String.Compare(szMathSymbols, szLetterLike)==0?"true":"false") );
// Unicode Mathematical operators
let charArr1 = [| '\u2200'; '\u2202'; '\u200F'; '\u2205' |]
let szMathSymbols = String charArr1
// Unicode Letterlike Symbols
let charArr2 = [| '\u2111'; '\u2118'; '\u2122'; '\u2126' |]
let szLetterLike = String charArr2
// Compare Strings - the result is false
printfn $"The Strings are equal? %b{String.Compare(szMathSymbols, szLetterLike) = 0}"
' Unicode Mathematical operators
Dim charArr1() As Char = {ChrW(&H2200), ChrW(&H2202), _
ChrW(&H200F), ChrW(&H2205)}
Dim szMathSymbols As New String(charArr1)
' Unicode Letterlike Symbols
Dim charArr2() As Char = {ChrW(&H2111), ChrW(&H2118), _
ChrW(&H2122), ChrW(&H2126)}
Dim szLetterLike As New String(charArr2)
' Compare Strings - the result is false
Console.WriteLine("The strings are equal? " & _
CStr(szMathSymbols.Equals(szLetterLike)))
示例 3:使用字符数组的一部分并重复单个字符
以下示例演示如何从字符数组的一部分创建新 String 对象,以及如何创建包含单个字符多个匹配项的新 String 对象。
// Create a Unicode String with 5 Greek Alpha characters
String szGreekAlpha = new String('\u0391',5);
// Create a Unicode String with a Greek Omega character
String szGreekOmega = new String(new char [] {'\u03A9','\u03A9','\u03A9'},2,1);
String szGreekLetters = String.Concat(szGreekOmega, szGreekAlpha, szGreekOmega.Clone());
// Examine the result
Console.WriteLine(szGreekLetters);
// The first index of Alpha
int ialpha = szGreekLetters.IndexOf('\u0391');
// The last index of Omega
int iomega = szGreekLetters.LastIndexOf('\u03A9');
Console.WriteLine("The Greek letter Alpha first appears at index " + ialpha +
" and Omega last appears at index " + iomega + " in this String.");
// Create a Unicode String with 5 Greek Alpha characters
let szGreekAlpha = String('\u0391',5)
// Create a Unicode String with a Greek Omega character
let szGreekOmega = String([| '\u03A9'; '\u03A9'; '\u03A9' |],2,1)
let szGreekLetters = String.Concat(szGreekOmega, szGreekAlpha, szGreekOmega.Clone())
// Examine the result
printfn $"{szGreekLetters}"
// The first index of Alpha
let ialpha = szGreekLetters.IndexOf '\u0391'
// The last index of Omega
let iomega = szGreekLetters.LastIndexOf '\u03A9'
printfn $"The Greek letter Alpha first appears at index {ialpha} and Omega last appears at index {iomega} in this String."
' Create a Unicode String with 5 Greek Alpha characters
Dim szGreekAlpha As New String(ChrW(&H0391), 5)
' Create a Unicode String with a Greek Omega character
Dim szGreekOmega As New String(New Char() {ChrW(&H03A9), ChrW(&H03A9), _
ChrW(&H03A9)}, 2, 1)
Dim szGreekLetters As String = String.Concat(szGreekOmega, szGreekAlpha, _
szGreekOmega.Clone())
' Examine the result
Console.WriteLine(szGreekLetters)
' The first index of Alpha
Dim iAlpha As Integer = szGreekLetters.IndexOf(ChrW(&H0391))
' The last index of Omega
Dim iomega As Integer = szGreekLetters.LastIndexOf(ChrW(&H03A9))
Console.WriteLine("The Greek letter Alpha first appears at index {0}.", _
ialpha)
Console.WriteLIne("The Greek letter Omega last appears at index {0}.", _
iomega)
示例 4:使用指向字符数组的指针
以下示例演示如何从指向字符数组的指针创建新 String 对象。 必须使用编译器开关编译 /unsafe
C# 示例。
using System;
public class Example4
{
public static unsafe void Main()
{
char[] characters = { 'H', 'e', 'l', 'l', 'o', ' ',
'w', 'o', 'r', 'l', 'd', '!', '\u0000' };
string value;
fixed (char* charPtr = characters) {
value = new String(charPtr);
}
Console.WriteLine(value);
}
}
// The example displays the following output:
// Hello world!
#nowarn "9"
open System
let characters =
[| 'H'; 'e'; 'l'; 'l'; 'o'; ' '
'w'; 'o'; 'r'; 'l'; 'd'; '!'; '\u0000' |]
let value =
use charPtr = fixed characters
String charPtr
printfn $"{value}"
// The example displays the following output:
// Hello world!
示例 5:从指针实例化字符串和数组范围
以下示例检查句点或感叹号的字符数组的元素。 如果找到一个字符串,它将从标点符号前面的数组中的字符实例化一个字符串。 否则,它会实例化包含数组的全部内容的字符串。 必须使用编译器开关编译 /unsafe
C# 示例。
using System;
public class Example1
{
public static unsafe void Main()
{
char[] characters = { 'H', 'e', 'l', 'l', 'o', ' ',
'w', 'o', 'r', 'l', 'd', '!', '\u0000' };
String value;
fixed (char* charPtr = characters) {
int length = 0;
Char* iterator = charPtr;
while (*iterator != '\x0000')
{
if (*iterator == '!' || *iterator == '.')
break;
iterator++;
length++;
}
value = new String(charPtr, 0, length);
}
Console.WriteLine(value);
}
}
// The example displays the following output:
// Hello World
#nowarn "9"
open System
open FSharp.NativeInterop
let characters =
[| 'H'; 'e'; 'l'; 'l'; 'o'; ' '
'w'; 'o'; 'r'; 'l'; 'd'; '!'; '\u0000' |]
[<EntryPoint>]
let main _ =
use charPtr = fixed characters
let mutable length = 0
let mutable iterator = charPtr
let mutable broken = false
while not broken && NativePtr.read iterator <> '\u0000' do
if NativePtr.read iterator = '!' || NativePtr.read iterator = '.' then
broken <- true
else
iterator <- NativePtr.add iterator 1
length <- length + 1
String(charPtr, 0, length)
|> printfn "%s"
0
// The example displays the following output:
// Hello World
示例 6:将字符串从指针实例化到有符号字节数组
以下示例演示如何使用String(SByte*)构造函数创建类的String实例。
unsafe
{
// Null terminated ASCII characters in an sbyte array
String szAsciiUpper = null;
sbyte[] sbArr1 = new sbyte[] { 0x41, 0x42, 0x43, 0x00 };
// Instruct the Garbage Collector not to move the memory
fixed(sbyte* pAsciiUpper = sbArr1)
{
szAsciiUpper = new String(pAsciiUpper);
}
String szAsciiLower = null;
sbyte[] sbArr2 = { 0x61, 0x62, 0x63, 0x00 };
// Instruct the Garbage Collector not to move the memory
fixed(sbyte* pAsciiLower = sbArr2)
{
szAsciiLower = new String(pAsciiLower, 0, sbArr2.Length);
}
// Prints "ABC abc"
Console.WriteLine(szAsciiUpper + " " + szAsciiLower);
// Compare Strings - the result is true
Console.WriteLine("The Strings are equal when capitalized ? " +
(String.Compare(szAsciiUpper.ToUpper(), szAsciiLower.ToUpper())==0?"true":"false") );
// This is the effective equivalent of another Compare method, which ignores case
Console.WriteLine("The Strings are equal when capitalized ? " +
(String.Compare(szAsciiUpper, szAsciiLower, true)==0?"true":"false") );
}
// Null terminated ASCII characters in an sbyte array
let szAsciiUpper =
let sbArr1 = [| 0x41y; 0x42y; 0x43y; 0x00y |]
// Instruct the Garbage Collector not to move the memory
use pAsciiUpper = fixed sbArr1
String pAsciiUpper
let szAsciiLower =
let sbArr2 = [| 0x61y; 0x62y; 0x63y; 0x00y |]
// Instruct the Garbage Collector not to move the memory
use pAsciiLower = fixed sbArr2
String(pAsciiLower, 0, sbArr2.Length)
// Prints "ABC abc"
printfn $"{szAsciiUpper} {szAsciiLower}"
// Compare Strings - the result is true
printfn $"The Strings are equal when capitalized ? %b{String.Compare(szAsciiUpper.ToUpper(), szAsciiLower.ToUpper()) = 0}"
// This is the effective equivalent of another Compare method, which ignores case
printfn $"The Strings are equal when capitalized ? %b{String.Compare(szAsciiUpper, szAsciiLower, true) = 0}"
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈