diff --git a/.openpublishing.redirection.csharp.json b/.openpublishing.redirection.csharp.json index 95d02d0fa394a..af3ce9352f131 100644 --- a/.openpublishing.redirection.csharp.json +++ b/.openpublishing.redirection.csharp.json @@ -1,577 +1,5 @@ { "redirections": [ - { - "source_path_from_root": "/docs/csharp/fundamentals/null-safety/migration-strategies.md", - "redirect_url": "/dotnet/csharp/advanced-topics/update-applications/nullable-migration-strategies" - }, - { - "source_path_from_root": "/docs/csharp/fundamentals/types/anonymous-types.md", - "redirect_url": "/dotnet/csharp/fundamentals/types/tuples" - }, - { - "source_path_from_root": "/docs/csharp/fundamentals/types/namespaces.md", - "redirect_url": "/dotnet/csharp/fundamentals/program-structure/namespaces" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0006.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0007.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0016.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1564.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1616.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1763.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs2032.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0017.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0028.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0031.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0059.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0123.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0144.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0148.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0220.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0221.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0273.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0274.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0275.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0276.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0406.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0409.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0410.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0411.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0442.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0452.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0453.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0456.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0463.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0543.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0544.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0546.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0547.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0548.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0594.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0610.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0644.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0652.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0659.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0693.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0699.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0701.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0704.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0712.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0718.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1021.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0080.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0081.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0305.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0306.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0307.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0308.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0312.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0313.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0314.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0315.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0401.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0402.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0403.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0405.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0407.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/lambda-expression-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0412.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0449.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0450.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0451.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0454.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0455.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0694.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0695.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0698.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0706.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0717.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0104.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0104" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0434.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0434" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0435.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0435" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0436.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0436" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0437.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0437" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs0438.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0438" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1022.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs1022" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1526.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1555.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1556.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1557.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1558.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1559.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1599.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1617.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/feature-version-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1638.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/feature-version-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1668.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1715.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1719.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1720.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1948.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs1958.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs2008.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs2017.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs2019.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs2029.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs2036.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs3012.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs3013.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs3024.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/misc/cs5001.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0304.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0310.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0311.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0413.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0417.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0467.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/lambda-expression-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0702.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0703.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/binary-literals.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/digit-separators.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/local-functions.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/statements#1364-local-function-declarations" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/throw-expression.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1215-the-throw-expression-operator" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/out-var.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1217-declaration-expressions" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/pattern-matching.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/patterns" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.0/task-types.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#15152-task-type-builder-pattern" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.1/async-main.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/basic-concepts#71-application-startup" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.1/target-typed-default.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12719-default-value-expressions" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.1/infer-tuple-names.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/types#8311-tuple-types" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.1/generics-pattern-match.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/patterns" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/conditional-ref.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1219-conditional-operator" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/non-trailing-named-arguments.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12621-general" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/private-protected.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#1536-access-modifiers" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/readonly-ref.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/readonly-struct.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/structs#1624-struct-interfaces" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.2/span-safety.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/auto-prop-field-attrs.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/attributes#223-attribute-specification" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/blittable.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#1525-type-parameter-constraints" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/expression-variables-in-initializers.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1217-declaration-expressions" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/improved-overload-candidates.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12642-applicable-function-member" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/indexing-movable-fixed-fields.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/unsafe-code#2383-fixed-size-buffers-in-expressions" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/leading-digit-separator.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/pattern-based-fixed.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/unsafe-code#247-the-fixed-statement" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/ref-local-reassignment.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/stackalloc-array-initializers.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12821-stack-allocation" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-7.3/tuple-equality.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#121211-tuple-equality-operators" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-9.0/nullable-reference-types-specification.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/types#893-nullable-reference-types" - }, - { - "source_path_from_root": "/redirections/proposals/csharp-10.0/generic-attributes.md", - "redirect_url": "/dotnet/csharp/language-reference/language-specification/attributes#232-attribute-classes" - }, { "source_path_from_root": "/docs/csharp/async.md", "redirect_url": "/dotnet/csharp/asynchronous-programming" @@ -648,6 +76,22 @@ "source_path_from_root": "/docs/csharp/features.md", "redirect_url": "/dotnet/csharp/programming-guide/concepts" }, + { + "source_path_from_root": "/docs/csharp/fundamentals/null-safety/migration-strategies.md", + "redirect_url": "/dotnet/csharp/advanced-topics/update-applications/nullable-migration-strategies" + }, + { + "source_path_from_root": "/docs/csharp/fundamentals/null-safety/resolve-warnings.md", + "redirect_url": "/dotnet/csharp/fundamentals/null-safety/common-tasks/resolve-warnings" + }, + { + "source_path_from_root": "/docs/csharp/fundamentals/types/anonymous-types.md", + "redirect_url": "/dotnet/csharp/fundamentals/types/tuples" + }, + { + "source_path_from_root": "/docs/csharp/fundamentals/types/namespaces.md", + "redirect_url": "/dotnet/csharp/fundamentals/program-structure/namespaces" + }, { "source_path_from_root": "/docs/csharp/generics.md", "redirect_url": "/dotnet/csharp/fundamentals/types/generics" @@ -719,10 +163,30 @@ "source_path_from_root": "/docs/csharp/getting-started/with-visual-studio.md", "redirect_url": "/dotnet/core/tutorials/with-visual-studio" }, + { + "source_path_from_root": "/docs/csharp/how-to/compare-strings.md", + "redirect_url": "/dotnet/csharp/fundamentals/strings/common-tasks/compare" + }, + { + "source_path_from_root": "/docs/csharp/how-to/concatenate-multiple-strings.md", + "redirect_url": "/dotnet/csharp/fundamentals/strings/common-tasks/concatenate" + }, + { + "source_path_from_root": "/docs/csharp/how-to/modify-string-contents.md", + "redirect_url": "/dotnet/csharp/fundamentals/strings/common-tasks/modify" + }, + { + "source_path_from_root": "/docs/csharp/how-to/parse-strings-using-split.md", + "redirect_url": "/dotnet/csharp/fundamentals/strings/split" + }, { "source_path_from_root": "/docs/csharp/how-to/safely-cast-using-pattern-matching-is-and-as-operators.md", "redirect_url": "/dotnet/csharp/fundamentals/tutorials/safely-cast-using-pattern-matching-is-and-as-operators" }, + { + "source_path_from_root": "/docs/csharp/how-to/search-strings.md", + "redirect_url": "/dotnet/csharp/fundamentals/strings/search" + }, { "source_path_from_root": "/docs/csharp/implicitly-typed-lambda-expressions.md", "redirect_url": "/dotnet/csharp/language-reference/operators/lambda-expressions" @@ -763,6 +227,18 @@ "source_path_from_root": "/docs/csharp/language-reference/builtin-types/nint-nuint.md", "redirect_url": "/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#native-sized-integers" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0006.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0007.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0016.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0034.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" @@ -811,6 +287,30 @@ "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0270.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0304.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0310.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0311.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0413.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0417.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0467.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/lambda-expression-errors" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0518.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0518" @@ -851,6 +351,14 @@ "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0686.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/interface-implementation-errors" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0702.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0703.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs0767.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/ref-modifiers-errors" @@ -923,10 +431,18 @@ "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1502.md", "redirect_url": "/dotnet/csharp/misc/cs1503" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1564.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1614.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1616.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1656.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/unsafe-code-errors" @@ -975,6 +491,10 @@ "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1751.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1763.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1919.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/unsafe-code-errors" @@ -1011,6 +531,10 @@ "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs1997.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/async-await-errors" }, + { + "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs2032.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/language-reference/compiler-messages/cs3007.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" @@ -2213,10 +1737,22 @@ "source_path_from_root": "/docs/csharp/misc/cs0012.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/assembly-references" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0017.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0022.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0028.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0031.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0035.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" @@ -2229,6 +1765,22 @@ "source_path_from_root": "/docs/csharp/misc/cs0057.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0059.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0080.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0081.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0104.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0104" + }, { "source_path_from_root": "/docs/csharp/misc/cs0105.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" @@ -2241,6 +1793,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0121.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0123.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, { "source_path_from_root": "/docs/csharp/misc/cs0132.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/constructor-errors#static-constructors" @@ -2249,6 +1805,14 @@ "source_path_from_root": "/docs/csharp/misc/cs0138.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0144.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0148.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, { "source_path_from_root": "/docs/csharp/misc/cs0171.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/feature-version-errors" @@ -2329,6 +1893,14 @@ "source_path_from_root": "/docs/csharp/misc/cs0218.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0220.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0221.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0225.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" @@ -2393,6 +1965,22 @@ "source_path_from_root": "/docs/csharp/misc/cs0267.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/partial-declarations" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0273.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0274.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0275.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0276.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0277.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/interface-implementation-errors" @@ -2401,14 +1989,86 @@ "source_path_from_root": "/docs/csharp/misc/cs0282.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/partial-declarations" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0305.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0306.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0307.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0308.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0312.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0313.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0314.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0315.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0400.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/assembly-references" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0401.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0402.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0403.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0404.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0405.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0406.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0407.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/lambda-expression-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0409.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0410.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0411.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0412.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0415.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" @@ -2437,6 +2097,26 @@ "source_path_from_root": "/docs/csharp/misc/cs0432.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0434.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0434" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0435.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0435" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0436.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0436" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0437.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0437" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0438.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs0438" + }, { "source_path_from_root": "/docs/csharp/misc/cs0439.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" @@ -2445,6 +2125,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0440.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0442.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0447.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" @@ -2453,6 +2137,38 @@ "source_path_from_root": "/docs/csharp/misc/cs0448.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0449.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0450.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0451.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0452.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0453.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0454.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0455.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0456.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0457.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" @@ -2465,6 +2181,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0460.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/interface-implementation-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0463.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0466.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" @@ -2529,6 +2249,26 @@ "source_path_from_root": "/docs/csharp/misc/cs0541.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/interface-implementation-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0543.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0544.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0546.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0547.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0548.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0550.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/interface-implementation-errors" @@ -2613,6 +2353,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0591.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/parameter-argument-mismatch" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0594.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0599.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/parameter-argument-mismatch" @@ -2621,6 +2365,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0609.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0610.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0611.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" @@ -2665,6 +2413,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0643.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/parameter-argument-mismatch" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0644.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, { "source_path_from_root": "/docs/csharp/misc/cs0646.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" @@ -2673,6 +2425,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0647.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0652.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0653.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" @@ -2689,6 +2445,10 @@ "source_path_from_root": "/docs/csharp/misc/cs0658.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0659.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0660.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" @@ -2698,33 +2458,77 @@ "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, { - "source_path_from_root": "/docs/csharp/misc/cs0663.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" + "source_path_from_root": "/docs/csharp/misc/cs0663.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0668.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0674.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0685.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0687.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0693.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0694.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0695.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0698.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" }, { - "source_path_from_root": "/docs/csharp/misc/cs0668.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" + "source_path_from_root": "/docs/csharp/misc/cs0699.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" }, { - "source_path_from_root": "/docs/csharp/misc/cs0674.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" + "source_path_from_root": "/docs/csharp/misc/cs0701.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" }, { - "source_path_from_root": "/docs/csharp/misc/cs0685.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" + "source_path_from_root": "/docs/csharp/misc/cs0704.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" }, { - "source_path_from_root": "/docs/csharp/misc/cs0687.md", - "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" + "source_path_from_root": "/docs/csharp/misc/cs0706.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" }, { "source_path_from_root": "/docs/csharp/misc/cs0710.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/constructor-errors#constructor-declarations" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0712.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0715.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs0717.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs0718.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs0719.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" @@ -2881,6 +2685,14 @@ "source_path_from_root": "/docs/csharp/misc/cs1020.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1021.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1022.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors#cs1022" + }, { "source_path_from_root": "/docs/csharp/misc/cs1024.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/preprocessor-errors" @@ -2973,6 +2785,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1517.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/preprocessor-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1526.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/new-object-creation-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1529.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" @@ -3001,6 +2817,26 @@ "source_path_from_root": "/docs/csharp/misc/cs1554.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overloaded-operator-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1555.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1556.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1557.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1558.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1559.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1560.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/preprocessor-errors" @@ -3017,6 +2853,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1586.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1599.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, { "source_path_from_root": "/docs/csharp/misc/cs1605.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/ref-modifiers-errors" @@ -3029,6 +2869,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1611.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1617.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/feature-version-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1618.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" @@ -3093,6 +2937,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1637.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/iterator-yield" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1638.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/feature-version-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1641.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/unsafe-code-errors" @@ -3149,6 +2997,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1667.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/attribute-usage-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1668.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/misc/cs1670.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/params-arrays" @@ -3225,6 +3077,18 @@ "source_path_from_root": "/docs/csharp/misc/cs1714.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/assembly-references" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1715.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/property-declaration-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1719.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs1720.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1730.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" @@ -3269,6 +3133,10 @@ "source_path_from_root": "/docs/csharp/misc/cs1945.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/expression-tree-restrictions" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1948.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs1950.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" @@ -3289,22 +3157,62 @@ "source_path_from_root": "/docs/csharp/misc/cs1954.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs1958.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/delegate-function-pointer-diagnostics" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs2008.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs2017.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs2019.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs2029.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/misc/cs2034.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/using-directive-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs2036.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/misc/cs3006.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/overload-resolution" }, + { + "source_path_from_root": "/docs/csharp/misc/cs3012.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, + { + "source_path_from_root": "/docs/csharp/misc/cs3013.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/invalid-build-command-line" + }, { "source_path_from_root": "/docs/csharp/misc/cs3016.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/array-declaration-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs3024.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/generic-type-parameters-errors" + }, { "source_path_from_root": "/docs/csharp/misc/CS4009.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/async-await-errors" }, + { + "source_path_from_root": "/docs/csharp/misc/cs5001.md", + "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/entry-point-errors" + }, { "source_path_from_root": "/docs/csharp/misc/cs8506.md", "redirect_url": "/dotnet/csharp/language-reference/compiler-messages/pattern-matching-warnings" @@ -5564,6 +5472,10 @@ "source_path_from_root": "/docs/csharp/tutorials/records.md", "redirect_url": "/dotnet/csharp/fundamentals/tutorials/records" }, + { + "source_path_from_root": "/docs/csharp/tutorials/string-interpolation.md", + "redirect_url": "/dotnet/csharp/fundamentals/tutorials/string-interpolation" + }, { "source_path_from_root": "/docs/csharp/tutorials/upgrade-to-nullable-references.md", "redirect_url": "/dotnet/csharp/advanced-topics/update-applications/nullable-migration-strategies" @@ -5673,6 +5585,122 @@ { "source_path_from_root": "/docs/csharp/write-safe-efficient-code.md", "redirect_url": "/dotnet/csharp/advanced-topics/performance" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-10.0/generic-attributes.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/attributes#232-attribute-classes" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/binary-literals.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/digit-separators.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/local-functions.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/statements#1364-local-function-declarations" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/out-var.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1217-declaration-expressions" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/pattern-matching.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/patterns" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/task-types.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#15152-task-type-builder-pattern" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.0/throw-expression.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1215-the-throw-expression-operator" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.1/async-main.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/basic-concepts#71-application-startup" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.1/generics-pattern-match.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/patterns" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.1/infer-tuple-names.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/types#8311-tuple-types" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.1/target-typed-default.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12719-default-value-expressions" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/conditional-ref.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1219-conditional-operator" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/non-trailing-named-arguments.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12621-general" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/private-protected.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#1536-access-modifiers" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/readonly-ref.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/readonly-struct.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/structs#1624-struct-interfaces" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.2/span-safety.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/auto-prop-field-attrs.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/attributes#223-attribute-specification" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/blittable.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/classes#1525-type-parameter-constraints" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/expression-variables-in-initializers.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#1217-declaration-expressions" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/improved-overload-candidates.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12642-applicable-function-member" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/indexing-movable-fixed-fields.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/unsafe-code#2383-fixed-size-buffers-in-expressions" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/leading-digit-separator.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/lexical-structure#6453-integer-literals" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/pattern-based-fixed.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/unsafe-code#247-the-fixed-statement" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/ref-local-reassignment.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/variables#97-reference-variables-and-returns" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/stackalloc-array-initializers.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#12821-stack-allocation" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-7.3/tuple-equality.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/expressions#121211-tuple-equality-operators" + }, + { + "source_path_from_root": "/redirections/proposals/csharp-9.0/nullable-reference-types-specification.md", + "redirect_url": "/dotnet/csharp/language-reference/language-specification/types#893-nullable-reference-types" } ] -} \ No newline at end of file +} diff --git a/docs/core/extensions/logging/library-guidance.md b/docs/core/extensions/logging/library-guidance.md index 754349cbbdcc2..602cc5c2ca9ad 100644 --- a/docs/core/extensions/logging/library-guidance.md +++ b/docs/core/extensions/logging/library-guidance.md @@ -74,7 +74,7 @@ For more information, see [Compile-time logging source generation](source-genera ## Avoid string interpolation in logging -A common mistake is to use [string interpolation](../../../csharp/tutorials/string-interpolation.md) to build log messages. String interpolation in logging is problematic for performance, as the string is evaluated even if the corresponding `LogLevel` isn't enabled. Instead of string interpolation, use the log message template, formatting, and argument list. For more information, see [Logging in .NET: Log message template](overview.md#log-message-template). +A common mistake is to use [string interpolation](../../../csharp/fundamentals/tutorials/string-interpolation.md) to build log messages. String interpolation in logging is problematic for performance, as the string is evaluated even if the corresponding `LogLevel` isn't enabled. Instead of string interpolation, use the log message template, formatting, and argument list. For more information, see [Logging in .NET: Log message template](overview.md#log-message-template). ## Use no-op logging defaults diff --git a/docs/csharp/advanced-topics/update-applications/nullable-migration-strategies.md b/docs/csharp/advanced-topics/update-applications/nullable-migration-strategies.md index 970c9c4fee6ba..f9acdb9040135 100644 --- a/docs/csharp/advanced-topics/update-applications/nullable-migration-strategies.md +++ b/docs/csharp/advanced-topics/update-applications/nullable-migration-strategies.md @@ -9,7 +9,7 @@ ai-usage: ai-assisted # Nullable migration strategies > [!TIP] -> **Starting a new project?** New projects created from .NET 6 or later templates already have `enable` set. You don't need a migration strategy: skip to [Resolve nullable warnings](../../fundamentals/null-safety/resolve-warnings.md). +> **Starting a new project?** New projects created from .NET 6 or later templates already have `enable` set. You don't need a migration strategy: skip to [Resolve nullable warnings](../../fundamentals/null-safety/common-tasks/resolve-warnings.md). > > **Maintaining an existing codebase?** Read [Nullable reference types](../../fundamentals/null-safety/nullable-reference-types.md) first to understand contexts, annotations, and null-state. This article assumes you're familiar with those concepts and ready to plan a rollout. @@ -49,7 +49,7 @@ The most predictable way to migrate a large project is to enable warnings or ann 1. Pick a file. Start with the deepest leaf types in your dependency graph, then move outward. Annotating a type causes new warnings in its callers, so working bottom-up minimizes rework. 1. Add the `#nullable` directive that opts the file into the new behavior. Use `#nullable enable` if you want both flags. Use `#nullable enable warnings` for warning-only. -1. Address the warnings in the file using the techniques in [Resolve nullable warnings](../../fundamentals/null-safety/resolve-warnings.md). +1. Address the warnings in the file using the techniques in [Resolve nullable warnings](../../fundamentals/null-safety/common-tasks/resolve-warnings.md). 1. Repeat for the next file. 1. When every file in the project has its directive, remove the directives and set `enable` at the project level. @@ -71,7 +71,7 @@ Lead with warnings when fixing latent enable [!TIP] -> **New to nullable reference types?** Read [Nullable reference types](nullable-reference-types.md) first to understand annotations and null-state analysis. This article assumes you're seeing warnings in a project where the feature is enabled. +> **New to nullable reference types?** Read [Nullable reference types](../nullable-reference-types.md) first to understand annotations and null-state analysis. This article assumes you're seeing warnings in a project where the feature is enabled. > -> **Looking for a specific compiler error code?** The [Resolve nullable warnings](../../language-reference/compiler-messages/nullable-warnings.md) reference article catalogs every CS86xx warning with the matching technique. +> **Looking for a specific compiler error code?** The [Resolve nullable warnings](../../../language-reference/compiler-messages/nullable-warnings.md) reference article catalogs every CS86xx warning with the matching technique. When you enable nullable reference types, the compiler issues warnings everywhere your code's behavior doesn't match its annotations. Most warnings fall into a small set of patterns. Once you recognize the pattern, the fix is usually one of five techniques: @@ -42,13 +42,13 @@ The fix is usually a *guard clause*. A *guard clause* is a check at the top of a :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="DereferenceFixed"::: -[Pattern matching](../../language-reference/operators/patterns.md) (expressions such as `is null` or `is { }` that test the shape of a value), `??`, and `??=` include null checks: +[Pattern matching](../../../language-reference/operators/patterns.md) (expressions such as `is null` or `is { }` that test the shape of a value), `??`, and `??=` include null checks: :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="NullOperatorsFix"::: The property pattern `{ Length: > 0 }` matches only when `message` is non-null *and* its `Length` property is greater than zero, so the compiler treats `message` as *not-null* inside the `if` block. A simpler `is not null` test produces the same null-state narrowing without inspecting any properties. -For an in-depth tour of the operators, see [Null operators](null-operators.md). +For an in-depth tour of the operators, see [Null operators](../null-operators.md). ## Adjust annotations @@ -73,7 +73,7 @@ Sometimes the right fix isn't at the call site. A method's signature doesn't cap :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="MissingAttribute"::: -The body of `IsPresent` proves the argument isn't null when the method returns `true`, but the signature doesn't say so. Add a [nullable analysis attribute](../../language-reference/attributes/nullable-analysis.md) to make the contract part of the API: +The body of `IsPresent` proves the argument isn't null when the method returns `true`, but the signature doesn't say so. Add a [nullable analysis attribute](../../../language-reference/attributes/nullable-analysis.md) to make the contract part of the API: :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="WithAttribute"::: @@ -84,21 +84,21 @@ Common attributes include: - — the listed members are *not-null* after the method returns. - — the method never returns normally (for example, it always throws). -The full list is in [Nullable static analysis attributes](../../language-reference/attributes/nullable-analysis.md). +The full list is in [Nullable static analysis attributes](../../../language-reference/attributes/nullable-analysis.md). ## Initialize non-nullable members -A constructor warning means a non-nullable field, property, or [auto-property](../../programming-guide/classes-and-structs/auto-implemented-properties.md) (a property that uses the compiler-generated backing field, such as `public string Name { get; set; }`) exits the constructor without being assigned a non-null value: +A constructor warning means a non-nullable field, property, or [auto-property](../../../programming-guide/classes-and-structs/auto-implemented-properties.md) (a property that uses the compiler-generated backing field, such as `public string Name { get; set; }`) exits the constructor without being assigned a non-null value: :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="UninitializedMember"::: You have several ways to address it. Pick the one that best matches your design intent. -**Require the value as a constructor argument.** Use a [primary constructor](../../whats-new/tutorials/primary-constructors.md) (parameters declared on the type itself, available throughout the body) or a regular constructor that initializes the property: +**Require the value as a constructor argument.** Use a [primary constructor](../../../whats-new/tutorials/primary-constructors.md) (parameters declared on the type itself, available throughout the body) or a regular constructor that initializes the property: :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="ConstructorInjected"::: -**Make the property `required`.** The caller must initialize it through an [object initializer](../../programming-guide/classes-and-structs/object-and-collection-initializers.md) (the `{ Property = value }` syntax that follows `new`): +**Make the property `required`.** The caller must initialize it through an [object initializer](../../../programming-guide/classes-and-structs/object-and-collection-initializers.md) (the `{ Property = value }` syntax that follows `new`): :::code language="csharp" source="snippets/resolve-warnings/Program.cs" id="RequiredMember"::: @@ -123,18 +123,18 @@ New C# projects enable nullable reference types by default, so most code you wri The common supported values are `enable` (the default for new projects) and `disable`. If the element is missing, the project uses whatever default the SDK and target framework set. -If you need to enable nullable for only part of a file with `#nullable` directives, or use the partial `warnings` and `annotations` modes when migrating an existing codebase, see [Nullable migration strategies](../../advanced-topics/update-applications/nullable-migration-strategies.md). +If you need to enable nullable for only part of a file with `#nullable` directives, or use the partial `warnings` and `annotations` modes when migrating an existing codebase, see [Nullable migration strategies](../../../advanced-topics/update-applications/nullable-migration-strategies.md). ## Where to go next -When a warning doesn't fit any of these patterns, the [Resolve nullable warnings](../../language-reference/compiler-messages/nullable-warnings.md) reference article lists the technique for every CS86xx warning the compiler emits. +When a warning doesn't fit any of these patterns, the [Resolve nullable warnings](../../../language-reference/compiler-messages/nullable-warnings.md) reference article lists the technique for every CS86xx warning the compiler emits. -To plan a migration that progressively enables nullable reference types in an existing codebase, see [Nullable migration strategies](../../advanced-topics/update-applications/nullable-migration-strategies.md). +To plan a migration that progressively enables nullable reference types in an existing codebase, see [Nullable migration strategies](../../../advanced-topics/update-applications/nullable-migration-strategies.md). ## Related content -- [Nullable reference types](nullable-reference-types.md) -- [Null operators](null-operators.md) -- [Nullable migration strategies](../../advanced-topics/update-applications/nullable-migration-strategies.md) -- [Nullable static analysis attributes](../../language-reference/attributes/nullable-analysis.md) -- [Resolve nullable warnings (compiler reference)](../../language-reference/compiler-messages/nullable-warnings.md) +- [Nullable reference types](../nullable-reference-types.md) +- [Null operators](../null-operators.md) +- [Nullable migration strategies](../../../advanced-topics/update-applications/nullable-migration-strategies.md) +- [Nullable static analysis attributes](../../../language-reference/attributes/nullable-analysis.md) +- [Resolve nullable warnings (compiler reference)](../../../language-reference/compiler-messages/nullable-warnings.md) diff --git a/docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/Program.cs b/docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/Program.cs similarity index 100% rename from docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/Program.cs rename to docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/Program.cs diff --git a/docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/project-snippet.xml b/docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/project-snippet.xml similarity index 100% rename from docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/project-snippet.xml rename to docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/project-snippet.xml diff --git a/docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/resolve-warnings.csproj b/docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/resolve-warnings.csproj similarity index 100% rename from docs/csharp/fundamentals/null-safety/snippets/resolve-warnings/resolve-warnings.csproj rename to docs/csharp/fundamentals/null-safety/common-tasks/snippets/resolve-warnings/resolve-warnings.csproj diff --git a/docs/csharp/fundamentals/null-safety/nullable-reference-types.md b/docs/csharp/fundamentals/null-safety/nullable-reference-types.md index 200dbe9698a27..04473b0c63e23 100644 --- a/docs/csharp/fundamentals/null-safety/nullable-reference-types.md +++ b/docs/csharp/fundamentals/null-safety/nullable-reference-types.md @@ -110,7 +110,7 @@ Initialize array elements as part of creating the array. [Collection expressions ## Related content - [Tutorial: Express your design intent with nullable and non-nullable reference types](../tutorials/nullable-reference-types.md) -- [Resolve nullable warnings](resolve-warnings.md) +- [Resolve nullable warnings](./common-tasks/resolve-warnings.md) - [Nullable migration strategies](../../advanced-topics/update-applications/nullable-migration-strategies.md) - [Nullable static analysis attributes](../../language-reference/attributes/nullable-analysis.md) - [Resolve nullable warnings (compiler reference)](../../language-reference/compiler-messages/nullable-warnings.md) diff --git a/docs/csharp/fundamentals/strings/common-tasks/compare.md b/docs/csharp/fundamentals/strings/common-tasks/compare.md new file mode 100644 index 0000000000000..a9d1fcee19f08 --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/compare.md @@ -0,0 +1,69 @@ +--- +title: "Compare strings in C#" +description: Learn how to compare strings in C# for equality and order, when ordinal beats culture-aware comparison, and how to sort collections of strings. +ms.date: 05/28/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# Compare strings in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** C# `==` on strings is *value* equality, like Java's `String.equals` or JavaScript's `===`, not Java-style reference comparison. The catch is the comparison rules: `==` and default to **ordinal** (byte-for-byte), while defaults to **current culture**. Python developers used to `==` returning a single answer should pass a value whenever case or locale matters. + +A string comparison answers one of two questions: + +- *Are these two strings equivalent?* — use or the `==` operator. +- *Which one comes first when sorted?* — use , , or a . + +Both questions accept a argument that controls case sensitivity and whether the comparison uses ordinal or culture-aware rules. Pick the right value and most surprises go away. For an in-depth treatment of culture-aware comparison and globalization concerns, see [String operations](../../../language-reference/builtin-types/string-operations.md) and [Best practices for comparing strings](../../../../standard/base-types/best-practices-strings.md). + +## Default equality is ordinal, case-sensitive + +`==` and the parameterless compare strings byte-for-byte. Two strings that differ only in case aren't equal: + +:::code language="csharp" source="snippets/compare/Program.cs" id="EqualsDefault"::: + +This default is right for identifiers, file paths, protocol tokens, and anything else that the program (not a human) defines. + +## Ignore case with an `OrdinalIgnoreCase` comparison + +To compare without regard to case, pass to the overload or to : + +:::code language="csharp" source="snippets/compare/Program.cs" id="IgnoreCase"::: + +`Compare` returns 0 for equal, a negative integer when the first argument sorts first, and a positive integer when it sorts after. + +## Pick a `StringComparison` value + +Different categories of text deserve different comparison rules. Use this guide: + +| What you're comparing | Use | +| ---------------------------------------------------- | ---------------------------------------------------------------------------------- | +| Paths, identifiers, URLs, protocol tokens | | +| The same data, but case-insensitive | | +| Text shown to the user | | +| Text shown to the user, case-insensitive | | +| Persisted data that must compare the same everywhere | | + +Ordinal comparison is the fastest and most predictable choice; culture-aware comparison applies locale-specific rules that vary by machine and platform. The following example shows the two flavors side by side: + +:::code language="csharp" source="snippets/compare/Program.cs" id="ComparePicker"::: + +## Sort a collection of strings + +Collections such as and accept a when you sort or search them. For machine-defined data, use or : + +:::code language="csharp" source="snippets/compare/Program.cs" id="SortCollection"::: + +Always use the same comparer for sorting and searching the same collection. Mixing them produces unpredictable results. For culture-sensitive sorting and the differences between linguistic and ordinal order, see [String operations](../../../language-reference/builtin-types/string-operations.md). + +## See also + +- +- +- +- [Best practices for comparing strings in .NET](../../../../standard/base-types/best-practices-strings.md) +- [String operations: pattern matching, performance, and span-based search](../../../language-reference/builtin-types/string-operations.md) diff --git a/docs/csharp/fundamentals/strings/common-tasks/concatenate.md b/docs/csharp/fundamentals/strings/common-tasks/concatenate.md new file mode 100644 index 0000000000000..3928b095060ff --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/concatenate.md @@ -0,0 +1,64 @@ +--- +title: "Concatenate strings in C#" +description: Learn how to join strings in C# with the + and += operators, string interpolation, StringBuilder, and string.Join, and when to choose each. +ms.date: 05/28/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# Concatenate strings in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** C# joins strings with the same `+` operator you might know from Java or JavaScript, and with template-style syntax (`$"Hello, {name}"`) that resembles JavaScript template literals or Python f-strings. Unlike Python, strings in C# are immutable: every `+` produces a new . For loops or large amounts of text, use the way Java developers reach for `StringBuilder` and Python developers reach for `"".join(...)`. + +C# gives you four everyday tools for joining strings. The right choice depends on how many pieces you're combining and where the values come from: + +- `+` and `+=` for one-off concatenation of a fixed set of values. +- *String interpolation* (`$"..."`) for readable templates that mix literal text and expressions. +- for loops and incremental building. +- for joining the elements of a collection with a separator. + +For deeper coverage of `String.Format`, , and allocation-free building with , see [String operations](../../../language-reference/builtin-types/string-operations.md). + +## Combine values with `+` and `+=` + +The `+` operator concatenates two strings into a new one; `+=` appends to an existing variable. Both are easy to read and the C# compiler folds adjacent literal concatenations at compile time: + +:::code language="csharp" source="snippets/concatenate/Program.cs" id="PlusOperator"::: + +Reach for these operators when you're joining a handful of values. They produce a new string every time, so they aren't a good fit for loops. + +## Build templates with string interpolation + +When you mix literal text and values from variables or expressions, *string interpolation* keeps the intent obvious. Prefix the string with `$` and embed expressions in braces: + +:::code language="csharp" source="snippets/concatenate/Program.cs" id="Interpolation"::: + +Interpolation supports format strings, alignment, and culture control. For a deeper walk-through, see [Tutorial: Learn string interpolation](../../tutorials/string-interpolation.md) and the [interpolated string](../../../language-reference/tokens/interpolated.md) reference. + +## Accumulate text with `StringBuilder` + +When you build a string piece-by-piece, especially inside a loop, use . It keeps a growable buffer so each append doesn't allocate a new string: + +:::code language="csharp" source="snippets/concatenate/Program.cs" id="StringBuilder"::: + +Call once at the end to produce the final string. + +## Join the elements of a collection + +When you already have an array or list of values, is the simplest option. Pass a separator and the collection: + +:::code language="csharp" source="snippets/concatenate/Program.cs" id="Join"::: + +`string.Join` walks the collection once and allocates the final string directly, which is faster than building it up with `+=`. + +## See also + +- +- +- +- [Interpolated string token](../../../language-reference/tokens/interpolated.md) +- [Tutorial: Learn string interpolation](../../tutorials/string-interpolation.md) +- [String operations: pattern matching, performance, and span-based search](../../../language-reference/builtin-types/string-operations.md) diff --git a/docs/csharp/fundamentals/strings/common-tasks/modify.md b/docs/csharp/fundamentals/strings/common-tasks/modify.md new file mode 100644 index 0000000000000..6a43dfdb01bff --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/modify.md @@ -0,0 +1,62 @@ +--- +title: "Modify string contents in C#" +description: Learn how to produce a new C# string from an existing one with Replace, Trim, Remove, and Regex.Replace, and why every modification returns a new string. +ms.date: 05/28/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# Modify string contents in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** C# strings are immutable, like Java's `String` and Python's `str`, and unlike JavaScript strings only when you treat them as mutable buffers. Every method that "modifies" a string returns a new and leaves the original unchanged. If you store the result, assign it back to the variable. + +Because instances are immutable, the methods in this article produce a new string and leave the original untouched. Choose a technique based on what you're trying to change: + +- *Substitute known text*: . +- *Clean up whitespace*: , , . +- *Cut out a span of characters*: plus . +- *Substitute a pattern*: . + +For allocation-free construction with , see [String operations](../../../language-reference/builtin-types/string-operations.md). + +## Replace known text + + substitutes every occurrence of a substring (or character) with another value. The original string isn't changed; capture the return value: + +:::code language="csharp" source="snippets/modify/Program.cs" id="Replace"::: + +Use the `char` overload when you replace a single character. It avoids allocating a one-character string and is the most direct option. + +## Trim leading and trailing whitespace + +`Trim`, `TrimStart`, and `TrimEnd` return a copy of the string with whitespace removed from one or both ends: + +:::code language="csharp" source="snippets/modify/Program.cs" id="Trim"::: + +Overloads accept an array of `char` values when you want to strip specific punctuation rather than whitespace. + +## Remove a span of characters + +To delete a range from the middle of a string, find the start position with and pass it to : + +:::code language="csharp" source="snippets/modify/Program.cs" id="Remove"::: + +Always check that `IndexOf` returned a non-negative value before you call `Remove`. A negative result means the substring isn't present. + +## Substitute matches of a pattern + +When the text you want to replace follows a pattern rather than a fixed value, use . The overload that takes a delegate lets you compute the replacement for each match. The following example replaces `the` (or `The`, ignoring case) followed by whitespace, preserving the original capitalization: + +:::code language="csharp" source="snippets/modify/Program.cs" id="Regex"::: + +For a tour of regular-expression patterns and validation, see [String operations](../../../language-reference/builtin-types/string-operations.md) and [Regular expression language - quick reference](../../../../standard/base-types/regular-expression-language-quick-reference.md). + +## See also + +- +- +- [.NET regular expressions](../../../../standard/base-types/regular-expressions.md) +- [String operations: pattern matching, performance, and span-based search](../../../language-reference/builtin-types/string-operations.md) diff --git a/docs/csharp/fundamentals/strings/common-tasks/search.md b/docs/csharp/fundamentals/strings/common-tasks/search.md new file mode 100644 index 0000000000000..29eb9c3c776ab --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/search.md @@ -0,0 +1,63 @@ +--- +title: "Search strings in C#" +description: Learn how to find text within strings in C# with the Contains, StartsWith, EndsWith, IndexOf, and LastIndexOf methods, and how to choose the right StringComparison. +ms.date: 05/21/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# Search strings in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** C# `string` methods such as `Contains`, `StartsWith`, and `IndexOf` parallel methods in Java's `String` and JavaScript's `String.prototype`. The key difference is that some C# searches default to **ordinal, case-sensitive** comparison. Others default to the current culture's semantics. For user-facing searches, you might want to pass a value. + +The class includes methods that answer two everyday questions: + +- *Does this string contain that text?* — use , , or . +- *Where does that text occur?* — use or . + +More complex search and replacement algorithms can be built using regular expressions. For more information on regular expressions, and other string operations see the language reference article on [String operations](../../../language-reference/builtin-types/string-operations.md). + +## Check whether a string contains text + +Use `Contains`, `StartsWith`, or `EndsWith` to test for the presence of a substring: + +:::code language="csharp" source="snippets/search/Program.cs" id="contains"::: + +These methods default to **case-sensitive, ordinal** comparison. To accept user input or to ignore case for display text, pass a value such as or . + +When you search for a single character, use the `char` overload of `Contains`. It avoids allocating a one-character string and is more direct: + +:::code language="csharp" source="snippets/search/Program.cs" id="ContainsChar"::: + +## Locate the position of text + +`IndexOf` returns the zero-based index of the first occurrence of a substring (or character), and `LastIndexOf` returns the index of the last occurrence. Both return `-1` when the search text isn't present. Combine them to extract the text between two markers: + +:::code language="csharp" source="snippets/search/Program.cs" id="IndexOf"::: + +When you need every occurrence rather than the first or last, iterate by passing the previous result plus one as the `startIndex` argument, or switch to a regular expression. + +## Choose the right comparison + +Most search overloads accept an optional value. Pick it based on the kind of data you're searching: + +- If you're searching identifiers, file paths, protocol tokens, or anything else machine-defined, use . +- If you're searching the same kind of machine-defined data but want case insensitivity, use . +- If you're searching user-visible text where the current locale's rules should apply, use . +- If you're searching that same user-visible text and want to ignore case, use . +- If you're searching persisted data that must compare the same on every machine and culture, use (rarely needed). + +Ordinal comparison is the fastest option and the right default for anything that isn't natural-language text. Culture-aware comparison is significantly slower and can produce surprising results. For example, in some cultures the lowercase `i` doesn't match an uppercase `I`.Reserve it for searches that users perform against prose. + +For an in-depth treatment of culture-aware comparison, see [Best practices for comparing strings](../../../../standard/base-types/best-practices-strings.md). + +## See also + +- [String operations: pattern matching, performance, and span-based search](../../../language-reference/builtin-types/string-operations.md) +- [Best practices for comparing strings in .NET](../../../../standard/base-types/best-practices-strings.md) +- [Comparing strings](../../../../standard/base-types/comparing.md) +- +- diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/Program.cs b/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/Program.cs new file mode 100644 index 0000000000000..d6ecfe418c71e --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/Program.cs @@ -0,0 +1,91 @@ +namespace CompareStrings; + +public static class Program +{ + public static void Main() + { + EqualsDefault(); + Console.WriteLine(); + IgnoreCase(); + Console.WriteLine(); + ComparePicker(); + Console.WriteLine(); + SortCollection(); + } + + private static void EqualsDefault() + { + // + string root = @"C:\users"; + string root2 = @"C:\Users"; + + // Equals and == default to ordinal, case-sensitive comparison. + Console.WriteLine($"<{root}>.Equals(<{root2}>) = {root.Equals(root2)}"); + Console.WriteLine($"<{root}> == <{root2}> -> {root == root2}"); + // => .Equals() = False + // => == -> False + // + } + + private static void IgnoreCase() + { + // + string root = @"C:\users"; + string root2 = @"C:\Users"; + + bool equal = root.Equals(root2, StringComparison.OrdinalIgnoreCase); + int order = string.Compare(root, root2, StringComparison.OrdinalIgnoreCase); + + Console.WriteLine($"OrdinalIgnoreCase equal? {equal}"); + Console.WriteLine($"OrdinalIgnoreCase Compare result: {order}"); + // => OrdinalIgnoreCase equal? True + // => OrdinalIgnoreCase Compare result: 0 + // + } + + private static void ComparePicker() + { + // + // Machine-defined text: paths, identifiers, protocol tokens. + string path1 = "/api/users"; + string path2 = "/API/Users"; + Console.WriteLine($"Paths equal (Ordinal)? {path1.Equals(path2, StringComparison.Ordinal)}"); + Console.WriteLine($"Paths equal (OrdinalIgnoreCase)? {path1.Equals(path2, StringComparison.OrdinalIgnoreCase)}"); + // => Paths equal (Ordinal)? False + // => Paths equal (OrdinalIgnoreCase)? True + + // User-visible text: prefer CurrentCulture(IgnoreCase) so case and + // locale rules match what the user expects in the UI. + string title = "Pride and Prejudice"; + string typed = "PRIDE"; + bool match = title.StartsWith(typed, StringComparison.CurrentCultureIgnoreCase); + Console.WriteLine($"Title starts with '{typed}' (current culture, ignore case)? {match}"); + // => Title starts with 'PRIDE' (current culture, ignore case)? True + // + } + + private static void SortCollection() + { + // + string[] files = + [ + @"c:\public\TextFile.TXT", + @"c:\public\textfile.txt", + @"c:\public\testfile2.txt", + @"c:\public\Text.txt", + ]; + + // For file names, identifiers, and other machine-defined keys, + // use StringComparer.Ordinal (or OrdinalIgnoreCase). + Array.Sort(files, StringComparer.Ordinal); + foreach (string file in files) + { + Console.WriteLine(file); + } + // => c:\public\Text.txt + // => c:\public\TextFile.TXT + // => c:\public\testfile2.txt + // => c:\public\textfile.txt + // + } +} diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/compare.csproj b/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/compare.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/compare/compare.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.cs b/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.cs new file mode 100644 index 0000000000000..ad8ff6335b115 --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/Program.cs @@ -0,0 +1,74 @@ +using System.Text; + +namespace ConcatenateStrings; + +public static class Program +{ + public static void Main() + { + PlusOperator(); + Console.WriteLine(); + Interpolation(); + Console.WriteLine(); + UsingStringBuilder(); + Console.WriteLine(); + UsingJoin(); + } + + private static void PlusOperator() + { + // + string userName = "Ada"; + string greeting = "Hello, " + userName + "."; + Console.WriteLine(greeting); + // => Hello, Ada. + + greeting += " Welcome back!"; + Console.WriteLine(greeting); + // => Hello, Ada. Welcome back! + // + } + + private static void Interpolation() + { + // + string userName = "Ada"; + int unread = 3; + string status = $"Hello, {userName}. You have {unread} unread messages."; + Console.WriteLine(status); + // => Hello, Ada. You have 3 unread messages. + // + } + + private static void UsingStringBuilder() + { + // + var builder = new StringBuilder(); + for (int i = 1; i <= 5; i++) + { + builder.AppendLine($"Line {i}"); + } + Console.Write(builder.ToString()); + // => Line 1 + // => Line 2 + // => Line 3 + // => Line 4 + // => Line 5 + // + } + + private static void UsingJoin() + { + // + string[] words = ["The", "quick", "brown", "fox"]; + + string sentence = string.Join(' ', words); + Console.WriteLine(sentence); + // => The quick brown fox + + string csv = string.Join(", ", words); + Console.WriteLine(csv); + // => The, quick, brown, fox + // + } +} diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/concatenate.csproj b/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/concatenate.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/concatenate/concatenate.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.cs b/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.cs new file mode 100644 index 0000000000000..075d789a6d95d --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/Program.cs @@ -0,0 +1,95 @@ +using System.Text; +using System.Text.RegularExpressions; + +namespace ModifyStrings; + +public static class Program +{ + public static void Main() + { + Replace(); + Console.WriteLine(); + Trim(); + Console.WriteLine(); + Remove(); + Console.WriteLine(); + RegexReplace(); + } + + private static void Replace() + { + // + string source = "The mountains are behind the clouds today."; + + string updated = source.Replace("mountains", "peaks"); + Console.WriteLine(source); + Console.WriteLine(updated); + // => The mountains are behind the clouds today. + // => The peaks are behind the clouds today. + + // Replace every occurrence of a single character. + string spaced = source.Replace(' ', '_'); + Console.WriteLine(spaced); + // => The_mountains_are_behind_the_clouds_today. + // + } + + private static void Trim() + { + // + string padded = " I'm wider than I need to be. "; + + Console.WriteLine($"<{padded.Trim()}>"); + Console.WriteLine($"<{padded.TrimStart()}>"); + Console.WriteLine($"<{padded.TrimEnd()}>"); + // => + // => + // => < I'm wider than I need to be.> + // + } + + private static void Remove() + { + // + string source = "Many mountains are behind many clouds today."; + + string toRemove = "many "; + int index = source.IndexOf(toRemove); + string result = index >= 0 ? source.Remove(index, toRemove.Length) : source; + + Console.WriteLine(source); + Console.WriteLine(result); + // => Many mountains are behind many clouds today. + // => Many mountains are behind clouds today. + // + } + + private static void RegexReplace() + { + // + string source = "The mountains are still there behind the clouds today."; + string replacement = "many "; + + string updated = Regex.Replace( + source, + @"the\s", + match => + { + if (char.IsUpper(match.Value[0])) + { + var builder = new StringBuilder(replacement); + builder[0] = char.ToUpper(builder[0]); + return builder.ToString(); + } + + return replacement; + }, + RegexOptions.IgnoreCase); + + Console.WriteLine(source); + Console.WriteLine(updated); + // => The mountains are still there behind the clouds today. + // => Many mountains are still there behind many clouds today. + // + } +} diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/modify.csproj b/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/modify.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/modify/modify.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/search/Program.cs b/docs/csharp/fundamentals/strings/common-tasks/snippets/search/Program.cs new file mode 100644 index 0000000000000..0deacbd654d1e --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/search/Program.cs @@ -0,0 +1,65 @@ +namespace SearchStrings; + +public static class Program +{ + public static void Main() + { + Contains(); + Console.WriteLine(); + ContainsChar(); + Console.WriteLine(); + IndexOfExample(); + } + + private static void Contains() + { + // + string factMessage = "Extension methods have all the capabilities of regular static methods."; + + // Write the string and include the quotation marks. + Console.WriteLine($"\"{factMessage}\""); + + // Default comparisons are case sensitive. + bool containsSearchResult = factMessage.Contains("extension"); + Console.WriteLine($"""Contains "extension"? {containsSearchResult}"""); + + // For user-facing searches, pass a StringComparison value to control case and culture. + bool ignoreCaseSearchResult = factMessage.StartsWith("extension", StringComparison.CurrentCultureIgnoreCase); + Console.WriteLine($"""Starts with "extension"? {ignoreCaseSearchResult} (ignoring case)"""); + + bool endsWithSearchResult = factMessage.EndsWith(".", StringComparison.Ordinal); + Console.WriteLine($"Ends with '.'? {endsWithSearchResult}"); + // => "Extension methods have all the capabilities of regular static methods." + // => Contains "extension"? False + // => Starts with "extension"? True (ignoring case) + // => Ends with '.'? True + // + } + + private static void ContainsChar() + { + // + string path = "/usr/local/bin"; + bool hasSlash = path.Contains('/'); + Console.WriteLine($"Path contains '/': {hasSlash}"); + // => Path contains '/': True + // + } + + private static void IndexOfExample() + { + // + string factMessage = "Extension methods have all the capabilities of regular static methods."; + + Console.WriteLine($"\"{factMessage}\""); + + // Extract the text between the first and last occurrence of "methods". + int first = factMessage.IndexOf("methods") + "methods".Length; + int last = factMessage.LastIndexOf("methods"); + string between = factMessage.Substring(first, last - first); + Console.WriteLine($"""Substring between "methods" and "methods": '{between}'"""); + // => "Extension methods have all the capabilities of regular static methods." + // => Substring between "methods" and "methods": ' have all the capabilities of regular static ' + // + } +} diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/search/search.csproj b/docs/csharp/fundamentals/strings/common-tasks/snippets/search/search.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/search/search.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/split/Program.cs b/docs/csharp/fundamentals/strings/common-tasks/snippets/split/Program.cs new file mode 100644 index 0000000000000..0b0f4d8f715b6 --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/split/Program.cs @@ -0,0 +1,198 @@ +namespace SplitStrings; + +public static class Program +{ + public static void Main() + { + SplitWords(); + Console.WriteLine(); + IndexWords(); + Console.WriteLine(); + RepeatedSeparators(); + Console.WriteLine(); + MultiChar(); + Console.WriteLine(); + MultiCharGaps(); + Console.WriteLine(); + StringSeparators(); + Console.WriteLine(); + LimitCount(); + Console.WriteLine(); + TrimEntries(); + } + + private static void SplitWords() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // => + // => + // => + // => + // => + // => + // => + // => + // => + // + } + + private static void IndexWords() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + for (int i = 0; i < words.Length; i++) + { + Console.WriteLine($"Index {i}: <{words[i]}>"); + } + // => Index 0: + // => Index 1: + // => Index 2: + // => ... + // + } + + private static void RepeatedSeparators() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // The runs of spaces produce empty entries: + // => + // => + // => + // => <> + // => <> + // => <> + // => + // => ... + // + } + + private static void MultiChar() + { + // + char[] delimiters = [' ', ',', '.', ':', '\t']; + + string text = "one\ttwo three:four,five six seven"; + Console.WriteLine($"Original text: '{text}'"); + + string[] words = text.Split(delimiters); + Console.WriteLine($"{words.Length} words in text:"); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // => 7 words in text: + // => + // => + // => + // => + // => + // => + // => + // + } + + private static void MultiCharGaps() + { + // + char[] delimiters = [' ', ',', '.', ':', '\t']; + + string text = "one\ttwo :,five six seven"; + Console.WriteLine($"Original text: '{text}'"); + + string[] words = text.Split(delimiters); + Console.WriteLine($"{words.Length} words in text:"); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // => 7 words in text: + // => + // => + // => <> + // => <> + // => + // => + // => + // + } + + private static void StringSeparators() + { + // + string[] separators = ["<<", "..."]; + + string text = "one< 3 substrings in text: + // => one + // => two + // => three + } + + private static void LimitCount() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' ', 4, StringSplitOptions.None); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // => + // => + // => + // => + // + } + + private static void TrimEntries() + { + // + string numerals = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"; + string[] trimmed = numerals.Split(',', StringSplitOptions.TrimEntries); + + Console.WriteLine("Trimmed entries:"); + foreach (var word in trimmed) + { + Console.WriteLine($"<{word}>"); + } + + string[] untrimmed = numerals.Split(',', StringSplitOptions.None); + Console.WriteLine("Untrimmed entries:"); + foreach (var word in untrimmed) + { + Console.WriteLine($"<{word}>"); + } + // => Trimmed entries: <1> <2> ... <10> + // => Untrimmed entries: <1> < 2> ... < 10> + // + } +} diff --git a/docs/csharp/fundamentals/strings/common-tasks/snippets/split/split.csproj b/docs/csharp/fundamentals/strings/common-tasks/snippets/split/split.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/snippets/split/split.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/strings/common-tasks/split.md b/docs/csharp/fundamentals/strings/common-tasks/split.md new file mode 100644 index 0000000000000..155b9b528abde --- /dev/null +++ b/docs/csharp/fundamentals/strings/common-tasks/split.md @@ -0,0 +1,80 @@ +--- +title: "Split strings into substrings in C#" +description: Learn how to split a C# string into substrings with String.Split, including how to use multiple separators, limit the substring count, and trim or remove entries. +ms.date: 05/21/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# Split strings into substrings in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** `string.Split` is C#'s counterpart to Java's `String.split` and JavaScript's `String.prototype.split`. Unlike those languages, C# returns an array (`string[]`), not a list, and the separator argument is a character or string, not a regular expression. For pattern-based splitting, see . + +The method breaks a string into an array of substrings using one or more separators. It's the simplest way to parse delimited text such as words, CSV-style values, or protocol tokens. + +The method has many overloads, but they cover four independent decisions: + +- **Separators**: one `char`, an array of `char`, one `string`, or an array of `string`s. +- **Maximum result count**: cap the number of substrings returned. +- **Empty-entry handling**: keep empty substrings (the default) or drop them with . +- **Whitespace handling**: trim leading and trailing whitespace from each entry with . + +## Split a string into words + +To split a phrase on whitespace, pass `' '` as the separator: + +:::code language="csharp" source="snippets/split/Program.cs" id="SplitWords"::: + +Iterate the returned array with `for` to recover the position of each word: + +:::code language="csharp" source="snippets/split/Program.cs" id="IndexWords"::: + +If the input contains repeated instances of the separator character, `Split` produces empty entries, one for each "gap" between consecutive separators: + +:::code language="csharp" source="snippets/split/Program.cs" id="RepeatedSeparators"::: + +Pass `StringSplitOptions.RemoveEmptyEntries` to drop those empty entries, as shown later in this article. + +## Split on multiple separator characters + +When more than one character can act as a separator, pass them as an array. The following example treats spaces, commas, periods, colons, and tabs all as word boundaries: + +:::code language="csharp" source="snippets/split/Program.cs" id="MultiChar"::: + +Adjacent separators still produce empty entries: + +:::code language="csharp" source="snippets/split/Program.cs" id="MultiCharGaps"::: + +## Split on multicharacter separators + +To split on whole-word or multicharacter separators, pass an array of strings. The string-array overloads require a value. Use `RemoveEmptyEntries` when repeated separators would otherwise produce empty results: + +:::code language="csharp" source="snippets/split/Program.cs" id="StringSeparators"::: + +## Limit how many substrings you get back + +Pass a `count` argument to cap the number of results. The final entry holds everything that's left, including any remaining separators: + +:::code language="csharp" source="snippets/split/Program.cs" id="LimitCount"::: + +This pattern is handy for `key=value` pairs and other formats where only the first separator is meaningful. + +## Trim whitespace from each entry + +`StringSplitOptions.TrimEntries` strips leading and trailing whitespace from every returned substring. You can combine it with `RemoveEmptyEntries` for typical CSV-style cleanup: + +:::code language="csharp" source="snippets/split/Program.cs" id="TrimEntries"::: + +## Use regular expressions + +`Split` works well for fixed character or string delimiters. For pattern-based splitting, use . See [String operations](../../../language-reference/builtin-types/string-operations.md) for an introduction to regular expressions on strings. + +## See also + +- +- +- [String operations: pattern matching, performance, and span-based search](../../../language-reference/builtin-types/string-operations.md) +- [Extract elements from a string](../../../../standard/base-types/divide-up-strings.md) diff --git a/docs/csharp/fundamentals/strings/interpolation.md b/docs/csharp/fundamentals/strings/interpolation.md new file mode 100644 index 0000000000000..749671cd60964 --- /dev/null +++ b/docs/csharp/fundamentals/strings/interpolation.md @@ -0,0 +1,101 @@ +--- +title: "String interpolation in C#" +description: Learn how to build result strings in C# with string interpolation by embedding formatted expression results directly in a string literal. +ms.date: 05/21/2026 +ms.topic: concept-article +ai-usage: ai-assisted +--- + +# String interpolation in C\# + +> [!TIP] +> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../tour-of-csharp/tutorials/index.md) tutorials first. +> +> **Coming from another language?** String interpolation in C# works much like template literals in JavaScript (`` `${x}` ``) or f-strings in Python (`f"{x}"`). The expression inside `{}` can be any valid C# expression, and you can add format and alignment specifiers without leaving the string. + +*String interpolation* lets you embed expressions directly in a string literal by prefixing the literal with `$`: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="general"::: + +Each `{ }` is an *interpolation expression*. C# evaluates the expression, converts the result to a string by calling its `ToString()` method, and substitutes the text into the result. The string interpolation for a `null` expression is the empty string. In most cases, the default conversion produces the output you want, and you don't need to do anything more. + +Interpolated strings are a more readable alternative to , and they support the full [composite formatting](../../../standard/base-types/composite-formatting.md) feature set. Anything you can do with a classic positional format string—format specifiers, alignment, culture-aware formatting, and constant strings—you can also do with an interpolated string. The rest of this article covers those options. Reach for them only when you need finer control over the result; otherwise, the plain `$"{expression}"` form is enough. + +For the language-reference treatment of the syntax and the underlying handler types, see [interpolated string](../../language-reference/tokens/interpolated.md) reference. For performance-focused topics such as `Span` interpolation and custom interpolated string handlers, see [String operations](../../language-reference/builtin-types/string-operations.md). + +## Apply a format string + +To control how an expression result is formatted, follow the expression with a colon and a [standard or custom format string](../../../standard/base-types/formatting-types.md): + +```csharp +{:} +``` + +The following example formats a and a value: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="FormatString"::: + +## Set the field width and alignment + +To produce aligned output, follow the expression with a comma and a minimum field width. Positive widths right-align the value, and negative widths left-align it: + +```csharp +{,} +``` + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="alignment"::: + +When you need both alignment and a format string, put alignment first: + +```csharp +{,:} +``` + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="AlignmentAndFormat"::: + +If the formatted value is longer than the requested width, C# ignores the width and emits the full value. + +## Escape braces and use escape sequences + +Interpolated strings support the same escape sequences as ordinary string literals. To include a literal `{` or `}` character in the result, double it (`{{` or `}}`). + +For paths and other strings that contain backslashes, prefer an [interpolated raw string literal](../../language-reference/tokens/raw-string.md) (`$"""..."""`) over the older verbatim form (`$@"..."`). Raw string literals don't process escape sequences, so backslashes appear as-is: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="escapes"::: + +## Use a conditional expression + +The colon has special meaning inside an interpolation expression, so wrap a [conditional exoressuin](../../language-reference/operators/conditional-operator.md) in parentheses: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="conditional"::: + +## Span an expression across multiple lines + +For better readability, break long interpolation expressions across multiple lines. Multi-line interpolation expressions are available since C# 11. The following example adds newlines between the `{` and `}` characters to separate the interpolated expressions from the literal text: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="newlines"::: + +## Build constant strings + +You can build constant interpolated strings when every interpolated expression is a constant value.That makes it usable for attribute arguments, `switch` patterns, and other contexts that require compile-time constants: + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="ConstantInterpolated"::: + +## Format with a specific culture + +By default, an interpolated string formats values using , which affects date, number, and currency representations. For deterministic output, pass an explicit culture to : + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="culture"::: + +For invariant output (logs, file formats, machine-readable data), pass : + +:::code language="csharp" source="snippets/interpolation/Program.cs" id="invariant"::: + +## See also + +- [Interpolated string token](../../language-reference/tokens/interpolated.md) +- [String operations: pattern matching, performance, and span-based search](../../language-reference/builtin-types/string-operations.md) +- [Composite formatting](../../../standard/base-types/composite-formatting.md) +- [Formatting types in .NET](../../../standard/base-types/formatting-types.md) +- +- diff --git a/docs/csharp/fundamentals/strings/snippets/interpolation/Program.cs b/docs/csharp/fundamentals/strings/snippets/interpolation/Program.cs new file mode 100644 index 0000000000000..310b3c5f5a21c --- /dev/null +++ b/docs/csharp/fundamentals/strings/snippets/interpolation/Program.cs @@ -0,0 +1,180 @@ +using System.Globalization; + +namespace Interpolation; + +public static class Program +{ + public static void Main() + { + General(); + Console.WriteLine(); + FormatString(); + Console.WriteLine(); + Alignment(); + Console.WriteLine(); + AlignmentAndFormat(); + Console.WriteLine(); + Escapes(); + Console.WriteLine(); + Conditional(); + Console.WriteLine(); + Newlines(); + Console.WriteLine(); + ConstantInterpolated(); + Console.WriteLine(); + Culture(); + Console.WriteLine(); + Invariant(); + } + + private static void General() + { + // + double a = 3; + double b = 4; + Console.WriteLine($"Area of the right triangle with legs of {a} and {b} is {0.5 * a * b}"); + Console.WriteLine($"Length of the hypotenuse of the right triangle with legs of {a} and {b} is {CalculateHypotenuse(a, b)}"); + double CalculateHypotenuse(double leg1, double leg2) => Math.Sqrt(leg1 * leg1 + leg2 * leg2); + // => Area of the right triangle with legs of 3 and 4 is 6 + // => Length of the hypotenuse of the right triangle with legs of 3 and 4 is 5 + // + } + + private static void FormatString() + { + // + var date = new DateTime(1731, 11, 25); + Console.WriteLine($"On {date:dddd, MMMM dd, yyyy} L. Euler introduced the letter e to denote {Math.E:F5}."); + // => On Sunday, November 25, 1731 L. Euler introduced the letter e to denote 2.71828. + // + } + + private static void Alignment() + { + // + var titles = new Dictionary() + { + ["Doyle, Arthur Conan"] = "Hound of the Baskervilles, The", + ["London, Jack"] = "Call of the Wild, The", + ["Shakespeare, William"] = "Tempest, The" + }; + + Console.WriteLine("Author and Title List"); + Console.WriteLine(); + Console.WriteLine($"|{"Author",-25}|{"Title",30}|"); + foreach (var title in titles) + { + Console.WriteLine($"|{title.Key,-25}|{title.Value,30}|"); + } + // => Author and Title List + // => + // => |Author | Title| + // => |Doyle, Arthur Conan |Hound of the Baskervilles, The| + // => |London, Jack | Call of the Wild, The| + // => |Shakespeare, William | Tempest, The| + // + } + + private static void AlignmentAndFormat() + { + // + const int NameAlignment = -9; + const int ValueAlignment = 7; + double a = 3; + double b = 4; + Console.WriteLine($"Three classical Pythagorean means of {a} and {b}:"); + Console.WriteLine($"|{"Arithmetic",NameAlignment}|{0.5 * (a + b),ValueAlignment:F3}|"); + Console.WriteLine($"|{"Geometric",NameAlignment}|{Math.Sqrt(a * b),ValueAlignment:F3}|"); + Console.WriteLine($"|{"Harmonic",NameAlignment}|{2 / (1 / a + 1 / b),ValueAlignment:F3}|"); + // => Three classical Pythagorean means of 3 and 4: + // => |Arithmetic| 3.500| + // => |Geometric| 3.464| + // => |Harmonic | 3.429| + // + } + + private static void Escapes() + { + // + int[] xs = [1, 2, 7, 9]; + int[] ys = [7, 9, 12]; + Console.WriteLine($"Find the intersection of the {{{string.Join(", ", xs)}}} and {{{string.Join(", ", ys)}}} sets."); + // => Find the intersection of the {1, 2, 7, 9} and {7, 9, 12} sets. + + var userName = "Jane"; + var stringWithEscapes = $"C:\\Users\\{userName}\\Documents"; + var rawInterpolated = $"""C:\Users\{userName}\Documents"""; + Console.WriteLine(stringWithEscapes); + Console.WriteLine(rawInterpolated); + // => C:\Users\Jane\Documents + // => C:\Users\Jane\Documents + // + } + + private static void Conditional() + { + // + var rand = new Random(42); + for (int i = 0; i < 3; i++) + { + Console.WriteLine($"Coin flip: {(rand.NextDouble() < 0.5 ? "heads" : "tails")}"); + } + // + } + + private static void Newlines() + { + // + int[] numbers = [3, 1, 4, 1, 5, 9, 2, 6]; + Console.WriteLine($"Total: { + numbers.Sum() + }, average: {numbers.Average():F2}."); + // => Total: 31, average: 3.88. + // + } + + private static void ConstantInterpolated() + { + // + const string Audience = "world"; + const string Greeting = $"Hello, {Audience}!"; + Console.WriteLine(Greeting); + // => Hello, world! + // + } + + private static void Culture() + { + // + CultureInfo[] cultures = + [ + CultureInfo.GetCultureInfo("en-US"), + CultureInfo.GetCultureInfo("en-GB"), + CultureInfo.GetCultureInfo("nl-NL"), + CultureInfo.InvariantCulture + ]; + var date = new DateTime(2026, 5, 21, 12, 35, 31); + var number = 31_415_926.536; + foreach (var culture in cultures) + { + var cultureSpecificMessage = string.Create(culture, $"{date,23}{number,20:N3}"); + Console.WriteLine($"{culture.Name,-10}{cultureSpecificMessage}"); + } + // Output is similar to: + // => en-US 5/21/2026 12:35:31 PM 31,415,926.536 + // => en-GB 21/05/2026 12:35:31 31,415,926.536 + // => nl-NL 21-05-2026 12:35:31 31.415.926,536 + // => 05/21/2026 12:35:31 31,415,926.536 + // + } + + private static void Invariant() + { + // + var timestamp = new DateTime(2026, 5, 21, 15, 46, 24); + string message = string.Create(CultureInfo.InvariantCulture, $"Date and time in invariant culture: {timestamp}"); + Console.WriteLine(message); + // => Date and time in invariant culture: 05/21/2026 15:46:24 + // + } +} diff --git a/docs/csharp/fundamentals/strings/snippets/interpolation/interpolation.csproj b/docs/csharp/fundamentals/strings/snippets/interpolation/interpolation.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/fundamentals/strings/snippets/interpolation/interpolation.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/fundamentals/tutorials/nullable-reference-types.md b/docs/csharp/fundamentals/tutorials/nullable-reference-types.md index d5ea0af2d9eaf..6b2cd16aed837 100644 --- a/docs/csharp/fundamentals/tutorials/nullable-reference-types.md +++ b/docs/csharp/fundamentals/tutorials/nullable-reference-types.md @@ -178,6 +178,6 @@ The finished sample is in the [csharp/NullableIntroduction](https://github.com/d ## Related content - [Nullable reference types](../null-safety/nullable-reference-types.md) -- [Resolve nullable warnings](../null-safety/resolve-warnings.md) +- [Resolve nullable warnings](../null-safety/common-tasks/resolve-warnings.md) - [Nullable migration strategies](../../advanced-topics/update-applications/nullable-migration-strategies.md) - [Working with nullable reference types in EF Core](/ef/core/miscellaneous/nullable-reference-types) diff --git a/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs b/docs/csharp/fundamentals/tutorials/snippets/string-interpolation/Program.cs similarity index 83% rename from docs/csharp/tutorials/snippets/StringInterpolation/Program.cs rename to docs/csharp/fundamentals/tutorials/snippets/string-interpolation/Program.cs index bde39c0dfc6e0..6f9ba1a889365 100644 --- a/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs +++ b/docs/csharp/fundamentals/tutorials/snippets/string-interpolation/Program.cs @@ -1,15 +1,17 @@ -using System.Globalization; +using System.Globalization; namespace StringInterpolation; -class Program +public static class Program { - static void Main(string[] args) + public static void Main() { StringInterpolationExample(); Console.WriteLine(); SpecifyFormatString(); Console.WriteLine(); + SpecifyAlignment(); + Console.WriteLine(); SpecifyAlignmentAndFormat(); Console.WriteLine(); EscapeSequenceExample(); @@ -23,7 +25,6 @@ static void Main(string[] args) InvariantCultureExample(); Console.WriteLine(); InvariantCultureExampleOld(); - Console.WriteLine(); } private static void StringInterpolationExample() @@ -52,9 +53,8 @@ private static void SpecifyFormatString() private static void SpecifyAlignment() { - // - var titles = new Dictionary() + Dictionary titles = new() { ["Doyle, Arthur Conan"] = "Hound of the Baskervilles, The", ["London, Jack"] = "Call of the Wild, The", @@ -70,7 +70,7 @@ private static void SpecifyAlignment() } // Output: // Author and Title List - // + // // |Author | Title| // |Doyle, Arthur Conan |Hound of the Baskervilles, The| // |London, Jack | Call of the Wild, The| @@ -100,17 +100,17 @@ private static void SpecifyAlignmentAndFormat() private static void EscapeSequenceExample() { // - var xs = new int[] { 1, 2, 7, 9 }; - var ys = new int[] { 7, 9, 12 }; - Console.WriteLine($"Find the intersection of the {{{string.Join(", ",xs)}}} and {{{string.Join(", ",ys)}}} sets."); + int[] xs = [1, 2, 7, 9]; + int[] ys = [7, 9, 12]; + Console.WriteLine($"Find the intersection of the {{{string.Join(", ", xs)}}} and {{{string.Join(", ", ys)}}} sets."); // Output: // Find the intersection of the {1, 2, 7, 9} and {7, 9, 12} sets. - var userName = "Jane"; - var stringWithEscapes = $"C:\\Users\\{userName}\\Documents"; - var verbatimInterpolated = $@"C:\Users\{userName}\Documents"; + string userName = "Jane"; + string stringWithEscapes = $"C:\\Users\\{userName}\\Documents"; + string rawInterpolated = $"""C:\Users\{userName}\Documents"""; Console.WriteLine(stringWithEscapes); - Console.WriteLine(verbatimInterpolated); + Console.WriteLine(rawInterpolated); // Output: // C:\Users\Jane\Documents // C:\Users\Jane\Documents @@ -131,13 +131,13 @@ private static void ConditionalOperatorExample() private static void CultureSensitiveExample() { // - var cultures = new System.Globalization.CultureInfo[] - { - System.Globalization.CultureInfo.GetCultureInfo("en-US"), - System.Globalization.CultureInfo.GetCultureInfo("en-GB"), - System.Globalization.CultureInfo.GetCultureInfo("nl-NL"), - System.Globalization.CultureInfo.InvariantCulture - }; + CultureInfo[] cultures = + [ + CultureInfo.GetCultureInfo("en-US"), + CultureInfo.GetCultureInfo("en-GB"), + CultureInfo.GetCultureInfo("nl-NL"), + CultureInfo.InvariantCulture + ]; var date = DateTime.Now; var number = 31_415_926.536; foreach (var culture in cultures) @@ -156,13 +156,13 @@ private static void CultureSensitiveExample() private static void CultureSensitiveExampleOld() { // - var cultures = new System.Globalization.CultureInfo[] - { - System.Globalization.CultureInfo.GetCultureInfo("en-US"), - System.Globalization.CultureInfo.GetCultureInfo("en-GB"), - System.Globalization.CultureInfo.GetCultureInfo("nl-NL"), - System.Globalization.CultureInfo.InvariantCulture - }; + CultureInfo[] cultures = + [ + CultureInfo.GetCultureInfo("en-US"), + CultureInfo.GetCultureInfo("en-GB"), + CultureInfo.GetCultureInfo("nl-NL"), + CultureInfo.InvariantCulture + ]; var date = DateTime.Now; var number = 31_415_926.536; FormattableString message = $"{date,23}{number,20:N3}"; diff --git a/docs/csharp/tutorials/snippets/StringInterpolation/string-interpolation.csproj b/docs/csharp/fundamentals/tutorials/snippets/string-interpolation/string-interpolation.csproj similarity index 79% rename from docs/csharp/tutorials/snippets/StringInterpolation/string-interpolation.csproj rename to docs/csharp/fundamentals/tutorials/snippets/string-interpolation/string-interpolation.csproj index 91b464afeacc1..bad583f080c8c 100644 --- a/docs/csharp/tutorials/snippets/StringInterpolation/string-interpolation.csproj +++ b/docs/csharp/fundamentals/tutorials/snippets/string-interpolation/string-interpolation.csproj @@ -1,10 +1,8 @@ - Exe - net8.0 - enable + net10.0 enable + enable - diff --git a/docs/csharp/tutorials/string-interpolation.md b/docs/csharp/fundamentals/tutorials/string-interpolation.md similarity index 61% rename from docs/csharp/tutorials/string-interpolation.md rename to docs/csharp/fundamentals/tutorials/string-interpolation.md index fd94d98d9a8c3..17311bdefc6a9 100644 --- a/docs/csharp/tutorials/string-interpolation.md +++ b/docs/csharp/fundamentals/tutorials/string-interpolation.md @@ -1,19 +1,21 @@ --- -title: String interpolation +title: "Tutorial: Learn string interpolation" description: Learn how to include formatted expression results in a result string in C# with string interpolation. author: pkulikov ms.subservice: fundamentals -ms.date: 11/18/2025 +ms.date: 05/28/2026 +ms.topic: tutorial +ai-usage: ai-assisted --- -# String interpolation in C\# +# Tutorial: Learn string interpolation in C\# -This tutorial shows you how to use [string interpolation](../language-reference/tokens/interpolated.md) to format and include expression results in a result string. The examples assume that you're familiar with basic C# concepts and .NET type formatting. For more information about formatting types in .NET, see [Formatting types in .NET](../../standard/base-types/formatting-types.md). +This tutorial shows you how to use [string interpolation](../../language-reference/tokens/interpolated.md) to format and include expression results in a result string. The examples assume that you're familiar with basic C# concepts and .NET type formatting. For more information about formatting types in .NET, see [Formatting types in .NET](../../../standard/base-types/formatting-types.md). ## Introduction To identify a string literal as an interpolated string, prepend it with the `$` symbol. You can embed any valid C# expression that returns a value in an interpolated string. In the following example, as soon as an expression is evaluated, its result is converted into a string and included in a result string: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="General"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="General"::: As the example shows, you include an expression in an interpolated string by enclosing it with braces: @@ -21,7 +23,7 @@ As the example shows, you include an expression in an interpolated string by enc {} ``` -Interpolated strings support all the capabilities of the [string composite formatting](../../standard/base-types/composite-formatting.md) feature. That makes them a more readable alternative to the use of the method. Every interpolated string must have: +Interpolated strings support all the capabilities of the [string composite formatting](../../../standard/base-types/composite-formatting.md) feature. That makes them a more readable alternative to the use of the method. Every interpolated string must have: - A string literal that begins with the `$` character before its opening quotation mark character. There can't be any spaces between the `$` symbol and the quotation mark character. - One or more *interpolation expressions*. You indicate an interpolation expression with an opening and closing brace (`{` and `}`). You can put any C# expression that returns a value (including `null`) inside the braces. @@ -41,9 +43,9 @@ To specify a format string supported by the type of the expression result, follo The following example shows how to specify standard and custom format strings for expressions that produce date and time or numeric results: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="FormatString"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="FormatString"::: -For more information, see the [Format string component](../../standard/base-types/composite-formatting.md#format-string-component) section of the [Composite formatting](../../standard/base-types/composite-formatting.md) article. +For more information, see the [Format string component](../../../standard/base-types/composite-formatting.md#format-string-component) section of the [Composite formatting](../../../standard/base-types/composite-formatting.md) article. ## How to control the field width and alignment of the formatted interpolation expression @@ -55,7 +57,7 @@ To specify the minimum field width and the alignment of the formatted expression The following code sample uses the minimum field width to create a tabular output: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="AlignmentString"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="AlignmentString"::: If the *width* value is positive, the formatted expression result is right-aligned; if negative, it's left-aligned. Remove the `-` signs before the width specifier and run the sample again to see the results. @@ -67,31 +69,29 @@ If you need to specify both width and a format string, start with the width comp The following example shows how to specify width and alignment, and uses pipe characters ("|") to delimit text fields: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="AlignmentAndFormatString"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="AlignmentAndFormatString"::: As the example output shows, if the length of the formatted expression result exceeds specified field width, the *width* value is ignored. -For more information, see the [Width component](../../standard/base-types/composite-formatting.md#width-component) section of the [Composite formatting](../../standard/base-types/composite-formatting.md) article. +For more information, see the [Width component](../../../standard/base-types/composite-formatting.md#width-component) section of the [Composite formatting](../../../standard/base-types/composite-formatting.md) article. ## How to use escape sequences in an interpolated string -Interpolated strings support all escape sequences that can be used in ordinary string literals. For more information, see [String escape sequences](../programming-guide/strings/index.md#string-escape-sequences). +Interpolated strings support all escape sequences that can be used in ordinary string literals. For more information, see [String escape sequences](../../programming-guide/strings/index.md#string-escape-sequences). -To interpret escape sequences literally, use a [verbatim](../language-reference/tokens/verbatim.md) string literal. An interpolated verbatim string starts with both the `$` and `@` characters. You can use `$` and `@` in any order: both `$@"..."` and `@$"..."` are valid interpolated verbatim strings. +To interpret escape sequences literally, use an [interpolated raw string literal](../../language-reference/tokens/interpolated.md#interpolated-raw-string-literals). Raw string literals are delimited by three or more quotation marks and don't process escape sequences. -To include a brace, "{" or "}", in a result string, use two braces, "{{" or "}}". For more information, see the [Escaping braces](../../standard/base-types/composite-formatting.md#escaping-braces) section of the [Composite formatting](../../standard/base-types/composite-formatting.md) article. +To include a brace, "{" or "}", in a result string, use two braces, "{{" or "}}". For more information, see the [Escaping braces](../../../standard/base-types/composite-formatting.md#escaping-braces) section of the [Composite formatting](../../../standard/base-types/composite-formatting.md) article. -The following example shows how to include braces in a result string and construct a verbatim interpolated string: +The following example shows how to include braces in a result string and contrasts an escaped interpolated string with an interpolated raw string literal: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="Escapes"::: - -You can use [interpolated raw string literals](../language-reference/tokens/interpolated.md#interpolated-raw-string-literals). +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="Escapes"::: ## How to use a ternary conditional operator `?:` in an interpolation expression -As the colon (":") has special meaning in an item with an interpolation expression, in order to use a [conditional operator](../language-reference/operators/conditional-operator.md) in an expression, enclose it in parentheses, as the following example shows: +As the colon (":") has special meaning in an item with an interpolation expression, in order to use a [conditional operator](../../language-reference/operators/conditional-operator.md) in an expression, enclose it in parentheses, as the following example shows: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="ConditionalOperator"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="ConditionalOperator"::: ## How to create a culture-specific result string with string interpolation @@ -99,11 +99,11 @@ By default, an interpolated string uses the current culture defined by the method to resolve an interpolated string to a culture-specific result string, as the following example shows: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="CultureSensitive"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="CultureSensitive"::: In earlier versions of .NET, use implicit conversion of an interpolated string to a instance and call its method to create a culture-specific result string. The following example shows how to do that: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="CultureSensitiveOld"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="CultureSensitiveOld"::: As the example shows, you can use one instance to generate multiple result strings for various cultures. @@ -111,19 +111,20 @@ As the example shows, you can use one instance t Beginning with .NET 6, use the method to resolve an interpolated string to a result string for the , as the following example shows: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="InvariantCulture"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="InvariantCulture"::: In earlier versions of .NET, along with the method, you can use the static method, as the following example shows: -:::code language="csharp" source="./snippets/StringInterpolation/Program.cs" id="InvariantCultureOld"::: +:::code language="csharp" source="./snippets/string-interpolation/Program.cs" id="InvariantCultureOld"::: ## Conclusion -This tutorial describes common scenarios of string interpolation usage. For more information about string interpolation, see [String interpolation](../language-reference/tokens/interpolated.md). For more information about formatting types in .NET, see the [Formatting types in .NET](../../standard/base-types/formatting-types.md) and [Composite formatting](../../standard/base-types/composite-formatting.md) articles. +This tutorial describes common scenarios of string interpolation usage. For more information about string interpolation, see [String interpolation](../../language-reference/tokens/interpolated.md). For more information about formatting types in .NET, see the [Formatting types in .NET](../../../standard/base-types/formatting-types.md) and [Composite formatting](../../../standard/base-types/composite-formatting.md) articles. ## See also - - - -- [Strings](../programming-guide/strings/index.md) +- [String interpolation](../strings/interpolation.md) +- [Strings](../../programming-guide/strings/index.md) diff --git a/docs/csharp/how-to/compare-strings.md b/docs/csharp/how-to/compare-strings.md deleted file mode 100644 index 1cf99d2c26a6f..0000000000000 --- a/docs/csharp/how-to/compare-strings.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "How to compare strings" -description: Learn how to compare and order string values, with or without case, with or without culture specific ordering. -ms.date: 02/18/2025 -helpviewer_keywords: - - "strings [C#], comparison" - - "comparing strings [C#]" ---- - -# How to compare strings in C\# - -You compare strings to answer one of two questions: "Are these two strings equal?" or "In what order should these strings be placed when sorting them?" - -The following factors complicate these two questions: - -- You can choose an ordinal or linguistic comparison. -- You can choose if case matters. -- You can choose culture-specific comparisons. -- Linguistic comparisons are culture and platform-dependent. - -The enumeration fields represent these choices: - -- **CurrentCulture**: Compare strings using culture-sensitive sort rules and the current culture. -- **CurrentCultureIgnoreCase**: Compare strings using culture-sensitive sort rules, the current culture, and ignoring the case of the strings being compared. -- **InvariantCulture**: Compare strings using culture-sensitive sort rules and the invariant culture. -- **InvariantCultureIgnoreCase**: Compare strings using culture-sensitive sort rules, the invariant culture, and ignoring the case of the strings being compared. -- **Ordinal**: Compare strings using ordinal (binary) sort rules. -- **OrdinalIgnoreCase**: Compare strings using ordinal (binary) sort rules and ignoring the case of the strings being compared. - -When you compare strings, you define an order among them. Comparisons are used to sort a sequence of strings. Once the sequence is in a known order, it's easier to search, both for software and for humans. Other comparisons might check if strings are the same. These sameness checks are similar to equality, but some differences, such as case differences, might be ignored. - -## Default ordinal comparisons - -By default, the most common operations: - -- -- and , that is, [equality operators `==` and `!=`](../language-reference/operators/equality-operators.md#string-equality), respectively perform a case-sensitive, ordinal comparison. has an overload where a argument can be provided to alter its sorting rules. The following example demonstrates that: - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet1"::: - -The default ordinal comparison doesn't take linguistic rules into account when comparing strings. It compares the binary value of each object in two strings. As a result, the default ordinal comparison is also case-sensitive. - -The test for equality with and the `==` and `!=` operators differs from string comparison using the and methods. They all perform a case-sensitive comparison. However, while the tests for equality perform an ordinal comparison, the `CompareTo` and `Compare` methods perform a culture-aware linguistic comparison using the current culture. Make the intent of your code clear by calling an overload that explicitly specifies the type of comparison to perform. - -You can use the [`is`](../language-reference/operators/is.md) operator and a [constant pattern](../language-reference/operators/patterns.md#constant-pattern) as an alternative to `==` when the right operand is a constant. - -## Case-insensitive ordinal comparisons - -The method enables you to specify a value of - for a case-insensitive ordinal comparison. There's also a static method that performs a case-insensitive ordinal comparison if you specify a value of for the argument. These comparisons are shown in the following code: - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet2"::: - -These methods use the casing conventions of the [invariant culture](xref:System.Globalization.CultureInfo.InvariantCulture) when performing a case-insensitive ordinal comparison. - -## Linguistic comparisons - -Many string comparison methods (such as ) use linguistic rules for the _current culture_ by default to order their inputs. This linguistic comparison is sometimes referred to as "word sort order." When you perform a linguistic comparison, some nonalphanumeric Unicode characters might have special weights assigned. For example, the hyphen "-" might have a small weight assigned to it so that "co-op" and "coop" appear next to each other in sort order. Some nonprinting control characters might be ignored. In addition, some Unicode characters might be equivalent to a sequence of instances. The following example uses the phrase "They dance in the street." in German with the "ss" (U+0073 U+0073) in one string and 'ß' (U+00DF) in another. Linguistically (in Windows), "ss" is equal to the German Esszet: 'ß' character in both the "en-US" and "de-DE" cultures. - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet3"::: - -On Windows, before .NET 5, the sort order of "cop", "coop", and "co-op" changes when you change from a linguistic comparison to an ordinal comparison. The two German sentences also compare differently using the different comparison types. Before .NET 5, the .NET globalization APIs used [National Language Support (NLS)](/windows/win32/intl/national-language-support) libraries. In .NET 5 and later versions, the .NET globalization APIs use [International Components for Unicode (ICU)](https://icu.unicode.org/) libraries, which unify .NET's globalization behavior across all supported operating systems. - -## Comparisons using specific cultures - -The following example stores objects for the en-US and de-DE cultures. The comparisons are performed using a object to ensure a culture-specific comparison. The culture used affects linguistic comparisons. The following example shows the results of comparing the two German sentences using the "en-US" culture and the "de-DE" culture: - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet4"::: - -Culture-sensitive comparisons are typically used to compare and sort strings input by users with other strings input by users. The characters and sorting conventions of these strings might vary depending on the locale of the user's computer. Even strings that contain identical characters might sort differently depending on the culture of the current thread. - -## Linguistic sorting and searching strings in arrays - -The following examples show how to sort and search for strings in an array using a linguistic comparison dependent on the current culture. You use the static methods that take a parameter. - -The following example shows how to sort an array of strings using the current culture: - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet5"::: - -Once the array is sorted, you can search for entries using a binary search. A binary search starts in the middle of the collection to determine which half of the collection would contain the sought string. Each subsequent comparison subdivides the remaining part of the collection in half. The array is sorted using the . The local function `ShowWhere` displays information about where the string was found. If the string wasn't found, the returned value indicates where it would be if it were found. - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet6"::: - -## Ordinal sorting and searching in collections - -The following code uses the collection class to store strings. The strings are sorted using the method. This method needs a delegate that compares and orders two strings. The method provides that comparison function. Run the sample and observe the order. This sort operation uses an ordinal case-sensitive sort. You would use the static methods to specify different comparison rules. - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet7"::: - -Once sorted, the list of strings can be searched using a binary search. The following sample shows how to search the sorted list using the same comparison function. The local function `ShowWhere` shows where the sought text is or would be: - -:::code language="csharp" source="./snippets/strings/CompareStrings.cs" id="Snippet8"::: - -Always make sure to use the same type of comparison for sorting and searching. Using different comparison types for sorting and searching produces unexpected results. - -Collection classes such as , , and have constructors that take a parameter when the type of the elements or keys is `string`. In general, you should use these constructors whenever possible, and specify either or . - -## See also - -- -- -- [Strings](../programming-guide/strings/index.md) -- [Comparing strings](../../standard/base-types/comparing.md) -- [Globalizing and localizing applications](/visualstudio/ide/globalizing-and-localizing-applications) diff --git a/docs/csharp/how-to/concatenate-multiple-strings.md b/docs/csharp/how-to/concatenate-multiple-strings.md deleted file mode 100644 index a8962971e8cfb..0000000000000 --- a/docs/csharp/how-to/concatenate-multiple-strings.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: "How to concatenate multiple strings" -description: There are multiple ways to concatenate strings in C#. Learn the options and the reasons behind different choices. -ms.date: 12/05/2025 -helpviewer_keywords: - - "joining strings [C#]" - - "concatenating strings [C#]" - - "strings [C#], concatenation" ---- -# How to concatenate multiple strings (C# Guide) - -*Concatenation* is the process of appending one string to the end of another string. You concatenate strings by using the `+` operator. For string literals and string constants, concatenation occurs at compile time; no run-time concatenation occurs. For string variables, concatenation occurs only at run time. - -## String literals - -The following example splits a long string literal into smaller strings to improve readability in the source code. The code concatenates the smaller strings to create the long string literal. The parts are concatenated into a single string at compile time. There's no run-time performance cost regardless of the number of strings involved. - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet1"::: - -## `+` and `+=` operators - -To concatenate string variables, you can use the `+` or `+=` operators, [string interpolation](../language-reference/tokens/interpolated.md) or the , , or methods. The `+` operator is easy to use and makes for intuitive code. Even if you use several `+` operators in one statement, the string content is copied only once. The following code shows examples of using the `+` and `+=` operators to concatenate strings: - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet2"::: - -## String interpolation - -In some expressions, it's easier to concatenate strings using string interpolation, as the following code shows: - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet3"::: - -> [!NOTE] -> In string concatenation operations, the C# compiler treats a null string the same as an empty string. - -You can use string interpolation to initialize a constant string when all the expressions used for placeholders are also constant strings. - -## `String.Format` - -Another method to concatenate strings is . This method works well when you're building a string from a few component strings. - -## `StringBuilder` - -In other cases, you might be combining strings in a loop where the actual number of source strings can be large. The class was designed for these scenarios. The following code uses the method of the class to concatenate strings. - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet4"::: - -You can read more about the [reasons to choose string concatenation or the `StringBuilder` class](/dotnet/api/system.text.stringbuilder#the-string-and-stringbuilder-types). - -## `String.Concat` or `String.Join` - -Another option to join strings from a collection is to use method. Use method if a delimiter should separate source strings. The following code combines an array of words using both methods: - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet5"::: - -## LINQ and `Enumerable.Aggregate` - -At last, you can use [LINQ](../linq/index.md) -and the method to join strings from a collection. This method combines -the source strings using a lambda expression. The lambda expression does the -work to add each string to the existing accumulation. The following example -combines an array of words, adding a space between each word in the array: - -:::code language="csharp" source="./snippets/strings/Concatenate.cs" id="Snippet6"::: - -This option can cause more allocations than other methods for concatenating collections, as it creates an intermediate string for each iteration. If optimizing performance is critical, consider the [`StringBuilder`](#stringbuilder) class or the [`String.Concat` or `String.Join`](#stringconcat-or-stringjoin) method to concatenate a collection, instead of `Enumerable.Aggregate`. - -## See also - -- -- -- [Strings](../programming-guide/strings/index.md) diff --git a/docs/csharp/how-to/index.md b/docs/csharp/how-to/index.md index 67bca16daef6d..9966fb8880776 100644 --- a/docs/csharp/how-to/index.md +++ b/docs/csharp/how-to/index.md @@ -41,12 +41,12 @@ These articles help you work with collections of data. Strings are the fundamental data type used to display or manipulate text. These articles demonstrate common practices with strings. -- [Compare strings](compare-strings.md). -- [Modify the contents of a string](modify-string-contents.md). +- [Compare strings](../fundamentals/strings/common-tasks/compare.md). +- [Modify the contents of a string](../fundamentals/strings/common-tasks/modify.md). - [Determine if a string represents a number](../programming-guide/strings/how-to-determine-whether-a-string-represents-a-numeric-value.md). -- [Use `String.Split` to separate strings](parse-strings-using-split.md). -- [Combine multiple strings into one](concatenate-multiple-strings.md). -- [Search for text in a string](search-strings.md). +- [Use `String.Split` to separate strings](../fundamentals/strings/common-tasks/split.md). +- [Combine multiple strings into one](../fundamentals/strings/common-tasks/concatenate.md). +- [Search for text in a string](../fundamentals/strings/common-tasks/search.md). ## Convert between types diff --git a/docs/csharp/how-to/modify-string-contents.md b/docs/csharp/how-to/modify-string-contents.md deleted file mode 100644 index d6136bcc7d2a3..0000000000000 --- a/docs/csharp/how-to/modify-string-contents.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "How to modify string contents" -description: Review examples of several techniques to modify existing string contents in C#, which return a new string object. -ms.date: 02/18/2025 -helpviewer_keywords: - - "strings [C#], modifying" ---- -# How to modify string contents in C\# - -This article demonstrates several techniques to produce a `string` by modifying an existing `string`. All the techniques demonstrated return the result of the modifications as a new `string` object. To demonstrate that the original and modified strings are distinct instances, the examples store the result in a new variable. You can examine the original `string` and the new, modified `string` when you run each example. - -There are several techniques demonstrated in this article. You can replace existing text. You can search for patterns and replace matching text with other text. You can treat a string as a sequence of characters. You can also use convenience methods that remove white space. Choose the techniques that most closely match your scenario. - -## Replace text - -The following code creates a new string by replacing existing text with a substitute. - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet1"::: - -The preceding code demonstrates this *immutable* property of strings. You can see in the preceding example that the original string, `source`, isn't modified. The method creates a new `string` containing the modifications. - -The method can replace either strings or single characters. In both cases, every occurrence of the sought text is replaced. The following example replaces all ' ' characters with '\_': - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet2"::: - -The source string is unchanged, and a new string is returned with the replacement. - -## Trim white space - -You can use the , , and methods to remove any leading or trailing white space. The following code shows an example of each. The source string doesn't change; these methods return a new string with the modified contents. - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet3"::: - -## Remove text - -You can remove text from a string using the method. This method removes the specified number of characters starting at a specific index. The following example shows how to use followed by to remove text from a string: - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet4"::: - -## Replace matching patterns - -You can use [regular expressions](../../standard/base-types/regular-expressions.md) to replace text matching patterns with new text, possibly defined by a pattern. The following example uses the class to find a pattern in a source string and replace it with proper capitalization. The method takes a function that provides the logic of the replacement as one of its arguments. In this example, that function, `LocalReplaceMatchCase` is a **local function** declared inside the sample method. `LocalReplaceMatchCase` uses the class to build the replacement string with proper capitalization. - -Regular expressions are most useful for searching and replacing text that follows a pattern, rather than known text. For more information, see [How to search strings](search-strings.md). The search pattern, "the\s" searches for the word "the" followed by a white-space character. That part of the pattern ensures that it doesn't match "there" in the source string. For more information on regular expression language elements, see [Regular Expression Language - Quick Reference](../../standard/base-types/regular-expression-language-quick-reference.md). - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet5"::: - -The method returns an immutable string with the contents in the object. - -## Modifying individual characters - -You can produce a character array from a string, modify the contents of the array, and then create a new string from the modified contents of the array. - -The following example shows how to replace a set of characters in a string. First, it uses the method to create an array of characters. It uses the method to find the starting index of the word "fox." The next three characters are replaced with a different word. Finally, a new string is constructed from the updated character array. - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet6"::: - -## Programmatically build up string content - -Since strings are immutable, the previous examples all create temporary strings or character arrays. In high-performance scenarios, it's desirable to avoid these heap allocations. .NET provides a method that allows you to programmatically fill in the character content of a string via a callback while avoiding the intermediate temporary string allocations. - -:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet7"::: - -You could modify a string in a fixed block with unsafe code, but it's **strongly** discouraged to modify the string content after a string is created. Doing so causes unpredictable bugs. For example, if someone interns a string that has the same content as yours, they get your copy and didn't expect that you're modifying their string. - -## See also - -- [.NET regular expressions](../../standard/base-types/regular-expressions.md) -- [Regular expression language - quick reference](../../standard/base-types/regular-expression-language-quick-reference.md) diff --git a/docs/csharp/how-to/parse-strings-using-split.md b/docs/csharp/how-to/parse-strings-using-split.md deleted file mode 100644 index 444c3161c1e38..0000000000000 --- a/docs/csharp/how-to/parse-strings-using-split.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: "Divide strings using String.Split" -description: The Split method returns an array of strings split from a set of delimiters. It's an easy way to extract substrings from a string. -ms.date: 12/05/2025 -helpviewer_keywords: - - "splitting strings [C#]" - - "Split method [C#]" - - "strings [C#], splitting" - - "parse strings" -ms.custom: copilot-scenario-highlight ---- -# How to separate strings using String.Split in C\# - -The method creates an array of substrings by splitting the input string based on one or more delimiters. This method is often the easiest way to separate a string on word boundaries. - -> [!TIP] -> You can use AI assistance to [split a string](#use-ai-to-split-a-string). - -## Split a string into words - -The following code splits a common phrase into an array of strings for each word. - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet1"::: - -Every instance of a separator character produces a value in the returned array. Since arrays in C# are zero-indexed, each string in the array is indexed from 0 to the value returned by the property minus 1: - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet1.5"::: - -The has many overloads. These overloads customize the behavior for splitting strings: - -- You can specify separators as `char` values or `string` values. -- You can specify one separator or multiple separators. If you specify multiple separators, they must all be the same type (either `char` or `string`). -- You can specify the maximum number of substrings to return. -- You can specify if repeated separator characters are ignored, or produce empty substrings in the return value. -- You can specify if leading and trailing whitespace is removed from the returned substrings. - -The remaining examples use different overloads to show each of these behaviors. - -For more information about indices, see the [Explore indexes and ranges](../tutorials/ranges-indexes.md) article. - -## Specify multiple separators - - can use multiple separator characters. The following example uses spaces, commas, periods, colons, and tabs as separating characters, which are passed to in an array. The loop at the bottom of the code displays each of the words in the returned array. - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet3"::: - -Consecutive instances of any separator produce the empty string in the output array: - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet4"::: - - can take an array of strings (character sequences that act as separators for parsing the target string, instead of single characters). - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet5"::: - -## Limit output size - -The following example shows how to limit the output to the first four substrings in the source string. - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet6"::: - -## Remove empty substrings - -Consecutive separator characters produce the empty string as a value in the returned array. You can see how an empty string is created in the following example, which uses the space character as a separator. - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet2"::: - -This behavior makes it easier for formats like comma-separated values (CSV) files representing tabular data. Consecutive commas represent a blank column. - -You can pass an optional parameter to exclude any empty strings in the returned array. For more complicated processing of the returned collection, you can use [LINQ](../linq/index.md) to manipulate the result sequence. - -## Trim whitespace - -The following example shows the effect of trimming entries: - -:::code language="csharp" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet7"::: - -The untrimmed entries have extra whitespace before the numerals. - -## Use AI to split a string - -You can use AI tools, such as GitHub Copilot, to generate code to split strings using `String.Split` in C#. You can customize the prompt to use strings and delimiters per your requirements. - -The following text shows an example prompt for Copilot Chat: - -```copilot-prompt -Generate C# code to parse and split CSV-style data from user input or external export that isn't well formed. -The input string may contain mixed delimiters (commas, semicolons), inconsistent spacing and empty entries. -Parse the string: accept all valid separators, remove any empty values and trim whitespace from all entries. -Return a clean list of values. -Show example output for the string: " apples, oranges ; bananas, , ;pears". -``` - -Review Copilot's suggestions before applying them. - -For more information, see [Copilot FAQs](https://aka.ms/copilot-general-use-faqs). - -## See also - -- [Extract elements from a string](../../standard/base-types/divide-up-strings.md) -- [Strings](../programming-guide/strings/index.md) -- [.NET regular expressions](../../standard/base-types/regular-expressions.md) -- [GitHub Copilot in Visual Studio](/visualstudio/ide/visual-studio-github-copilot-install-and-states) -- [GitHub Copilot in VS Code](https://code.visualstudio.com/docs/copilot/overview) diff --git a/docs/csharp/how-to/search-strings.md b/docs/csharp/how-to/search-strings.md deleted file mode 100644 index 53dab76b473ed..0000000000000 --- a/docs/csharp/how-to/search-strings.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "How to search strings" -description: Learn about two strategies to search for text in strings in C#. String class methods search for specific text. Regular expressions search for patterns in text. -ms.date: 02/18/2025 -helpviewer_keywords: - - "searching strings [C#]" - - "strings [C#], searching with String methods" - - "strings [C#], searching with regular expressions" ---- - -# How to search strings - -You can use two main strategies to search for text in strings. Methods of the class search for specific text. Regular expressions search for patterns in text. - -The [string](../language-reference/builtin-types/reference-types.md#the-string-type) type, which is an alias for the class, provides many useful methods for searching the contents of a string. Among them are , , , , . The class provides a rich vocabulary to search for patterns in text. In this article, you learn these techniques and how to choose the best method for your needs. - -## Does a string contain text? - -The , , and methods search a string for specific text. The following example shows each of these methods and a variation that uses a case-insensitive search: - -:::code language="csharp" source="./snippets/strings/SearchStrings.cs" id="Snippet1"::: - -The preceding example demonstrates an important point for using these methods. Searches are **case-sensitive** by default. You use the enumeration value to specify a case-insensitive search. - -## Where does the sought text occur in a string? - -The and methods also search for text in strings. These methods return the location of the text being sought. If the text isn't found, they return `-1`. The following example shows a search for the first and last occurrence of the word "methods" and displays the text in between. - -:::code language="csharp" source="./snippets/strings/SearchStrings.cs" id="Snippet2"::: - -## Finding specific text using regular expressions - -The class can be used to search strings. These searches can range in complexity from simple to complicated text patterns. - -The following code example searches for the word "the" or "their" in a sentence, ignoring case. The static method performs the search. You give it the string to search and a search pattern. In this case, a third argument specifies case-insensitive search. For more information, see . - -The search pattern describes the text you search for. The following table describes each element of the search pattern. (The following table uses the single `\`, which must be escaped as `\\` in a C# string). - -| Pattern | Meaning | -|----------|----------------------------------| -| `the` | match the text "the" | -| `(eir)?` | match 0 or 1 occurrence of "eir" | -| `\s` | match a white-space character | - -:::code language="csharp" source="./snippets/strings/SearchStrings.cs" id="Snippet3"::: - -> [!TIP] -> The `string` methods are generally better choices when you're searching for an exact string. Regular expressions are better when you're searching for some pattern in a source string. - -## Does a string follow a pattern? - -The following code uses regular expressions to validate the format of each string in an array. The validation requires that each string is formatted as a telephone number: three groups of digits separated by dashes where the first two groups contain three digits and the third group contains four digits. The search pattern uses the regular expression `^\\d{3}-\\d{3}-\\d{4}$`. For more information, see [Regular Expression Language - Quick Reference](../../standard/base-types/regular-expression-language-quick-reference.md). - -| Pattern | Meaning | -|---------|----------------------------------------| -| `^` | Matches the beginning of the string | -| `\d{3}` | Matches exactly three digit characters | -| `-` | Matches the '-' character | -| `\d{4}` | Matches exactly four digit characters | -| `$` | Matches the end of the string | - -:::code language="csharp" source="./snippets/\strings/SearchStrings.cs" id="Snippet4"::: - -This single search pattern matches many valid strings. Regular expressions are better to search for or validate against a pattern, rather than a single text string. - -## See also - -- [Strings](../programming-guide/strings/index.md) -- -- [.NET regular expressions](../../standard/base-types/regular-expressions.md) -- [Regular expression language - quick reference](../../standard/base-types/regular-expression-language-quick-reference.md) -- [Best practices for using strings in .NET](../../standard/base-types/best-practices-strings.md) diff --git a/docs/csharp/how-to/snippets/strings/CompareStrings.cs b/docs/csharp/how-to/snippets/strings/CompareStrings.cs deleted file mode 100644 index 032007728e697..0000000000000 --- a/docs/csharp/how-to/snippets/strings/CompareStrings.cs +++ /dev/null @@ -1,338 +0,0 @@ -namespace HowToStrings; - -public static class CompareStrings -{ - public static void Examples() - { - OrdinalDefaultComparisons(); - OrdinalIgnoreCaseComparisons(); - WordSortOrderInvariantCulture(); - LinguisticComparisons(); - - SortArrayOfStrings(); - SearchSortedArray(); - - SortListOfStrings(); - SearchSortedList(); - } - - private static void OrdinalDefaultComparisons() - { - // - string root = @"C:\users"; - string root2 = @"C:\Users"; - - bool result = root.Equals(root2); - Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - - result = root.Equals(root2, StringComparison.Ordinal); - Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - - Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}"); - // - } - - private static void OrdinalIgnoreCaseComparisons() - { - // - string root = @"C:\users"; - string root2 = @"C:\Users"; - - bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase); - bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase); - int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase); - - Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}"); - if (comparison < 0) - { - Console.WriteLine($"<{root}> is less than <{root2}>"); - } - else if (comparison > 0) - { - Console.WriteLine($"<{root}> is greater than <{root2}>"); - } - else - { - Console.WriteLine($"<{root}> and <{root2}> are equivalent in order"); - } - // - } - - private static void WordSortOrderInvariantCulture() - { - // - string first = "Sie tanzen auf der Straße."; - string second = "Sie tanzen auf der Strasse."; - - Console.WriteLine($"First sentence is <{first}>"); - Console.WriteLine($"Second sentence is <{second}>"); - - bool equal = String.Equals(first, second, StringComparison.InvariantCulture); - Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal."); - showComparison(first, second); - - string word = "coop"; - string words = "co-op"; - string other = "cop"; - - showComparison(word, words); - showComparison(word, other); - showComparison(words, other); - void showComparison(string one, string two) - { - int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture); - int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); - if (compareLinguistic < 0) - { - Console.WriteLine($"<{one}> is less than <{two}> using invariant culture"); - } - else if (compareLinguistic > 0) - { - Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture"); - } - else - { - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture"); - } - - if (compareOrdinal < 0) - { - Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); - } - else if (compareOrdinal > 0) - { - Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); - } - else - { - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); - } - } - // - } - private static void LinguisticComparisons() - { - // - string first = "Sie tanzen auf der Straße."; - string second = "Sie tanzen auf der Strasse."; - - Console.WriteLine($"First sentence is <{first}>"); - Console.WriteLine($"Second sentence is <{second}>"); - - var en = new System.Globalization.CultureInfo("en-US"); - - // For culture-sensitive comparisons, use the String.Compare - // overload that takes a StringComparison value. - int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None); - Console.WriteLine($"Comparing in {en.Name} returns {i}."); - - var de = new System.Globalization.CultureInfo("de-DE"); - i = String.Compare(first, second, de, System.Globalization.CompareOptions.None); - Console.WriteLine($"Comparing in {de.Name} returns {i}."); - - bool b = String.Equals(first, second, StringComparison.CurrentCulture); - Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal."); - - string word = "coop"; - string words = "co-op"; - string other = "cop"; - - showComparison(word, words, en); - showComparison(word, other, en); - showComparison(words, other, en); - void showComparison(string one, string two, System.Globalization.CultureInfo culture) - { - int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None); - int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); - if (compareLinguistic < 0) - { - Console.WriteLine($"<{one}> is less than <{two}> using en-US culture"); - } - else if (compareLinguistic > 0) - { - Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture"); - } - else - { - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture"); - } - - if (compareOrdinal < 0) - { - Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); - } - else if (compareOrdinal > 0) - { - Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); - } - else - { - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); - } - } - // - } - - private static void SortArrayOfStrings() - { - // - string[] lines = - [ - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - ]; - - Console.WriteLine("Non-sorted order:"); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - - Console.WriteLine("\n\rSorted order:"); - - // Specify Ordinal to demonstrate the different behavior. - Array.Sort(lines, StringComparer.CurrentCulture); - - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - // - } - - private static void SearchSortedArray() - { - // - string[] lines = - [ - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - ]; - Array.Sort(lines, StringComparer.CurrentCulture); - - string searchString = @"c:\public\TEXTFILE.TXT"; - Console.WriteLine($"Binary search for <{searchString}>"); - int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture); - ShowWhere(lines, result); - - Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); - - void ShowWhere(T[] array, int index) - { - if (index < 0) - { - index = ~index; - - Console.Write("Not found. Sorts between: "); - - if (index == 0) - { - Console.Write("beginning of sequence and "); - } - else - { - Console.Write($"{array[index - 1]} and "); - } - - if (index == array.Length) - { - Console.WriteLine("end of sequence."); - } - else - { - Console.WriteLine($"{array[index]}."); - } - } - else - { - Console.WriteLine($"Found at index {index}."); - } - } - // - } - - private static void SortListOfStrings() - { - // - List lines = - [ - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - ]; - - Console.WriteLine("Non-sorted order:"); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - - Console.WriteLine("\n\rSorted order:"); - - lines.Sort((left, right) => left.CompareTo(right)); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - // - } - - private static void SearchSortedList() - { - // - List lines = - [ - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - ]; - lines.Sort((left, right) => left.CompareTo(right)); - - string searchString = @"c:\public\TEXTFILE.TXT"; - Console.WriteLine($"Binary search for <{searchString}>"); - int result = lines.BinarySearch(searchString); - ShowWhere(lines, result); - - Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); - - void ShowWhere(IList collection, int index) - { - if (index < 0) - { - index = ~index; - - Console.Write("Not found. Sorts between: "); - - if (index == 0) - { - Console.Write("beginning of sequence and "); - } - else - { - Console.Write($"{collection[index - 1]} and "); - } - - if (index == collection.Count) - { - Console.WriteLine("end of sequence."); - } - else - { - Console.WriteLine($"{collection[index]}."); - } - } - else - { - Console.WriteLine($"Found at index {index}."); - } - } - // - } -} diff --git a/docs/csharp/how-to/snippets/strings/Concatenate.cs b/docs/csharp/how-to/snippets/strings/Concatenate.cs deleted file mode 100644 index b3e10829c5b20..0000000000000 --- a/docs/csharp/how-to/snippets/strings/Concatenate.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Text; - -namespace HowToStrings; - -static public class Concatenate -{ - public static void Examples() - { - UsingAddWithConstantStrings(); - UsingAddWithVariables(); - UsingInterpolationWithVariables(); - UsingStringBuilder(); - UsingConcatAndJoin(); - UsingAggregate(); - } - - private static void UsingAddWithConstantStrings() - { - // - // Concatenation of literals is performed at compile time, not run time. - string text = "Historically, the world of data and the world of objects " + - "have not been well integrated. Programmers work in C# or Visual Basic " + - "and also in SQL or XQuery. On the one side are concepts such as classes, " + - "objects, fields, inheritance, and .NET Framework APIs. On the other side " + - "are tables, columns, rows, nodes, and separate languages for dealing with " + - "them. Data types often require translation between the two worlds; there are " + - "different standard functions. Because the object world has no notion of query, a " + - "query can only be represented as a string without compile-time type checking or " + - "IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " + - "objects in memory is often tedious and error-prone."; - - Console.WriteLine(text); - // - } - - private static void UsingAddWithVariables() - { - // - string userName = ""; - string dateString = DateTime.Today.ToShortDateString(); - - // Use the + and += operators for one-time concatenations. - string str = "Hello " + userName + ". Today is " + dateString + "."; - Console.WriteLine(str); - - str += " How are you today?"; - Console.WriteLine(str); - // - } - private static void UsingInterpolationWithVariables() - { - // - string userName = ""; - string date = DateTime.Today.ToShortDateString(); - - // Use string interpolation to concatenate strings. - string str = $"Hello {userName}. Today is {date}."; - Console.WriteLine(str); - - str = $"{str} How are you today?"; - Console.WriteLine(str); - // - } - - private static void UsingStringBuilder() - { - // - // Use StringBuilder for concatenation in tight loops. - var sb = new StringBuilder(); - for (int i = 0; i < 20; i++) - { - sb.AppendLine(i.ToString()); - } - Console.WriteLine(sb.ToString()); - // - } - - private static void UsingConcatAndJoin() - { - // - string[] words = ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."]; - - var unreadablePhrase = string.Concat(words); - Console.WriteLine(unreadablePhrase); - - var readablePhrase = string.Join(" ", words); - Console.WriteLine(readablePhrase); - // - } - - private static void UsingAggregate() - { - // - string[] words = ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."]; - - var phrase = words.Aggregate((partialPhrase, word) =>$"{partialPhrase} {word}"); - Console.WriteLine(phrase); - // - } -} diff --git a/docs/csharp/how-to/snippets/strings/ModifyStrings.cs b/docs/csharp/how-to/snippets/strings/ModifyStrings.cs deleted file mode 100644 index 68982c1dd1e60..0000000000000 --- a/docs/csharp/how-to/snippets/strings/ModifyStrings.cs +++ /dev/null @@ -1,144 +0,0 @@ -namespace HowToStrings; - -public static class ModifyStrings -{ - public static void Examples() - { - ReplaceCreatesNewString(); - ReplaceChars(); - TrimWhitespace(); - RemoveText(); - ReplaceWithRegEx(); - ReplaceCharArray(); - UsingStringCreate(); - } - - private static void ReplaceCreatesNewString() - { - // - string source = "The mountains are behind the clouds today."; - - // Replace one substring with another with String.Replace. - // Only exact matches are supported. - var replacement = source.Replace("mountains", "peaks"); - Console.WriteLine($"The source string is <{source}>"); - Console.WriteLine($"The updated string is <{replacement}>"); - // - } - - private static void ReplaceChars() - { - // - string source = "The mountains are behind the clouds today."; - - // Replace all occurrences of one char with another. - var replacement = source.Replace(' ', '_'); - Console.WriteLine(source); - Console.WriteLine(replacement); - // - } - - private static void TrimWhitespace() - { - // - // Remove trailing and leading white space. - string source = " I'm wider than I need to be. "; - // Store the results in a new string variable. - var trimmedResult = source.Trim(); - var trimLeading = source.TrimStart(); - var trimTrailing = source.TrimEnd(); - Console.WriteLine($"<{source}>"); - Console.WriteLine($"<{trimmedResult}>"); - Console.WriteLine($"<{trimLeading}>"); - Console.WriteLine($"<{trimTrailing}>"); - // - } - - private static void RemoveText() - { - // - string source = "Many mountains are behind many clouds today."; - // Remove a substring from the middle of the string. - string toRemove = "many "; - string result = string.Empty; - int i = source.IndexOf(toRemove); - if (i >= 0) - { - result= source.Remove(i, toRemove.Length); - } - Console.WriteLine(source); - Console.WriteLine(result); - // - } - - private static void ReplaceWithRegEx() - { - // - string source = "The mountains are still there behind the clouds today."; - - // Use Regex.Replace for more flexibility. - // Replace "the" or "The" with "many" or "Many". - // using System.Text.RegularExpressions - string replaceWith = "many "; - source = System.Text.RegularExpressions.Regex.Replace(source, """the\s""", LocalReplaceMatchCase, - System.Text.RegularExpressions.RegexOptions.IgnoreCase); - Console.WriteLine(source); - - string LocalReplaceMatchCase(System.Text.RegularExpressions.Match matchExpression) - { - // Test whether the match is capitalized - if (Char.IsUpper(matchExpression.Value[0])) - { - // Capitalize the replacement string - System.Text.StringBuilder replacementBuilder = new System.Text.StringBuilder(replaceWith); - replacementBuilder[0] = Char.ToUpper(replacementBuilder[0]); - return replacementBuilder.ToString(); - } - else - { - return replaceWith; - } - } - // - } - - private static void ReplaceCharArray() - { - // - string phrase = "The quick brown fox jumps over the fence"; - Console.WriteLine(phrase); - - char[] phraseAsChars = phrase.ToCharArray(); - int animalIndex = phrase.IndexOf("fox"); - if (animalIndex != -1) - { - phraseAsChars[animalIndex++] = 'c'; - phraseAsChars[animalIndex++] = 'a'; - phraseAsChars[animalIndex] = 't'; - } - - string updatedPhrase = new string(phraseAsChars); - Console.WriteLine(updatedPhrase); - // - } - - private static void UsingStringCreate() - { - // - // constructing a string from a char array, prefix it with some additional characters - char[] chars = [ 'a', 'b', 'c', 'd', '\0' ]; - int length = chars.Length + 2; - string result = string.Create(length, chars, (Span strContent, char[] charArray) => - { - strContent[0] = '0'; - strContent[1] = '1'; - for (int i = 0; i < charArray.Length; i++) - { - strContent[i + 2] = charArray[i]; - } - }); - - Console.WriteLine(result); - // - } -} diff --git a/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs b/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs deleted file mode 100644 index 3e09ff2d24cd4..0000000000000 --- a/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs +++ /dev/null @@ -1,165 +0,0 @@ -namespace HowToStrings; - -public static class ParseStringsUsingSplit -{ - public static void Examples() - { - Console.WriteLine("Split words"); - Console.WriteLine(); - SplitWords(); - - Console.WriteLine("Enumerate words"); - Console.WriteLine(); - EnumerateWords(); - - Console.WriteLine("Split words with repeated separators"); - Console.WriteLine(); - SplitWordsWithRepeatedSeparators(); - - Console.WriteLine("Split on multiple chars"); - Console.WriteLine(); - SplitOnMultipleChars(); - - Console.WriteLine("Split on multiple chars with gaps"); - Console.WriteLine(); - SplitOnMultipleCharsWithGaps(); - - Console.WriteLine("Split using strings"); - Console.WriteLine(); - SplitUsingStrings(); - - Console.WriteLine("Split into no more than four substrings"); - Console.WriteLine(); - SplitFourTimes(); - - Console.WriteLine("Trim output substrings"); - Console.WriteLine(); - SplitAndTrim(); - } - - private static void SplitWords() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } - - private static void EnumerateWords() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - for (int i = 0; i < words.Length; i++) - { - Console.WriteLine($"Index {i}: <{words[i]}>"); - } - // - } - - private static void SplitWordsWithRepeatedSeparators() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitOnMultipleChars() - { - // - char[] delimiterChars = [' ', ',', '.', ':', '\t']; - - string text = "one\ttwo three:four,five six seven"; - Console.WriteLine($"Original text: '{text}'"); - - string[] words = text.Split(delimiterChars); - Console.WriteLine($"{words.Length} words in text:"); - - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitOnMultipleCharsWithGaps() - { - // - char[] delimiterChars = [' ', ',', '.', ':', '\t']; - - string text = "one\ttwo :,five six seven"; - Console.WriteLine($"Original text: '{text}'"); - - string[] words = text.Split(delimiterChars); - Console.WriteLine($"{words.Length} words in text:"); - - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitUsingStrings() - { - // - string[] separatingStrings = ["<<", "..."]; - - string text = "one< - } - - private static void SplitFourTimes() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' ', 4, StringSplitOptions.None); - - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitAndTrim() - { - // - string numerals = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10"; - string[] words = numerals.Split(',', StringSplitOptions.TrimEntries); - - Console.WriteLine("Trimmed entries:"); - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - words = numerals.Split(',', StringSplitOptions.None); - Console.WriteLine("Untrimmed entries:"); - foreach (var word in words) - { - Console.WriteLine($"<{word}>"); - } - // - } -} diff --git a/docs/csharp/how-to/snippets/strings/Program.cs b/docs/csharp/how-to/snippets/strings/Program.cs deleted file mode 100644 index 78067d0124cfb..0000000000000 --- a/docs/csharp/how-to/snippets/strings/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -using HowToStrings; - -Console.WriteLine("============================ String.Split examples ================================================="); -Console.WriteLine(); -ParseStringsUsingSplit.Examples(); -Console.WriteLine("============================ String concatenation examples ================================================="); -Console.WriteLine(); -Concatenate.Examples(); -Console.WriteLine("============================ String Searching examples ================================================="); -Console.WriteLine(); -SearchStrings.Examples(); -Console.WriteLine("============================ Modify string examples ================================================="); -Console.WriteLine(); -ModifyStrings.Examples(); -Console.WriteLine("============================ Compare string examples ================================================="); -Console.WriteLine(); -CompareStrings.Examples(); diff --git a/docs/csharp/how-to/snippets/strings/SearchStrings.cs b/docs/csharp/how-to/snippets/strings/SearchStrings.cs deleted file mode 100644 index ce92fe7d03d33..0000000000000 --- a/docs/csharp/how-to/snippets/strings/SearchStrings.cs +++ /dev/null @@ -1,117 +0,0 @@ -namespace HowToStrings; - -public class SearchStrings -{ - public static void Examples() - { - SearchWithMethods(); - SearchByIndex(); - RegularExpressionsOne(); - RegularExpressionsValidation(); - } - - private static void SearchWithMethods() - { - // - string factMessage = "Extension methods have all the capabilities of regular static methods."; - - // Write the string and include the quotation marks. - Console.WriteLine($"\"{factMessage}\""); - - // Simple comparisons are always case sensitive! - bool containsSearchResult = factMessage.Contains("extension"); - // Raw string literals can work here because the output doesn't begin with " - Console.WriteLine($"""Contains "extension"? {containsSearchResult}"""); - - // For user input and strings that will be displayed to the end user, - // use the StringComparison parameter on methods that have it to specify how to match strings. - bool ignoreCaseSearchResult = factMessage.StartsWith("extension", System.StringComparison.CurrentCultureIgnoreCase); - Console.WriteLine($"""Starts with "extension"? {ignoreCaseSearchResult} (ignoring case)"""); - - bool endsWithSearchResult = factMessage.EndsWith(".", System.StringComparison.CurrentCultureIgnoreCase); - Console.WriteLine($"Ends with '.'? {endsWithSearchResult}"); - // - } - - private static void SearchByIndex() - { - // - string factMessage = "Extension methods have all the capabilities of regular static methods."; - - // Write the string and include the quotation marks. - Console.WriteLine($"\"{factMessage}\""); - - // This search returns the substring between two strings, so - // the first index is moved to the character just after the first string. - int first = factMessage.IndexOf("methods") + "methods".Length; - int last = factMessage.LastIndexOf("methods"); - string str2 = factMessage.Substring(first, last - first); - Console.WriteLine($"""Substring between "methods" and "methods": '{str2}'"""); - // - } - - private static void RegularExpressionsOne() - { - // - string[] sentences = - [ - "Put the water over there.", - "They're quite thirsty.", - "Their water bottles broke." - ]; - - string sPattern = "the(ir)?\\s"; - - foreach (string s in sentences) - { - Console.Write($"{s,24}"); - - if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase)) - { - Console.WriteLine($" (match for '{sPattern}' found)"); - } - else - { - Console.WriteLine(); - } - } - // - } - - private static void RegularExpressionsValidation() - { - // - string[] numbers = - [ - "123-555-0190", - "444-234-22450", - "690-555-0178", - "146-893-232", - "146-555-0122", - "4007-555-0111", - "407-555-0111", - "407-2-5555", - "407-555-8974", - "407-2ab-5555", - "690-555-8148", - "146-893-232-" - ]; - - string sPattern = """^\d{3}-\d{3}-\d{4}$"""; - - foreach (string s in numbers) - { - Console.Write($"{s,14}"); - - if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern)) - { - Console.WriteLine(" - valid"); - } - else - { - Console.WriteLine(" - invalid"); - } - } - // - } -} diff --git a/docs/csharp/how-to/snippets/strings/strings.csproj b/docs/csharp/how-to/snippets/strings/strings.csproj deleted file mode 100644 index eeafa373ee0cf..0000000000000 --- a/docs/csharp/how-to/snippets/strings/strings.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - Exe - net9.0 - enable - enable - HowToStrings - true - - - diff --git a/docs/csharp/language-reference/builtin-types/snippets/string-operations/Program.cs b/docs/csharp/language-reference/builtin-types/snippets/string-operations/Program.cs new file mode 100644 index 0000000000000..570f045ca269a --- /dev/null +++ b/docs/csharp/language-reference/builtin-types/snippets/string-operations/Program.cs @@ -0,0 +1,178 @@ +using System.Globalization; +using System.Text.RegularExpressions; + +namespace StringOperations; + +public static class Program +{ + public static void Main() + { + RegexPattern(); + Console.WriteLine(); + RegexValidate(); + Console.WriteLine(); + SpanSearch(); + Console.WriteLine(); + FormatAndAggregate(); + Console.WriteLine(); + CultureDeepDive(); + Console.WriteLine(); + StringCreate(); + } + + private static void RegexPattern() + { + // + string[] sentences = + [ + "Put the water over there.", + "They're quite thirsty.", + "Their water bottles broke." + ]; + + string pattern = @"the(ir)?\s"; + + foreach (string s in sentences) + { + Console.Write($"{s,28}"); + + if (Regex.IsMatch(s, pattern, RegexOptions.IgnoreCase)) + { + Console.WriteLine($" (match for '{pattern}' found)"); + } + else + { + Console.WriteLine(); + } + } + // + } + + private static void RegexValidate() + { + // + string[] numbers = + [ + "123-555-0190", + "444-234-22450", + "690-555-0178", + "146-893-232", + "146-555-0122", + "4007-555-0111", + "407-555-0111", + "407-2-5555", + "407-555-8974", + "407-2ab-5555", + "690-555-8148", + "146-893-232-" + ]; + + string pattern = """^\d{3}-\d{3}-\d{4}$"""; + + foreach (string s in numbers) + { + Console.Write($"{s,14}"); + Console.WriteLine(Regex.IsMatch(s, pattern) ? " - valid" : " - invalid"); + } + // + } + + private static void SpanSearch() + { + // + ReadOnlySpan input = "key1=alpha;key2=beta;key3=gamma".AsSpan(); + ReadOnlySpan needle = "key2=".AsSpan(); + + int start = input.IndexOf(needle); + if (start >= 0) + { + ReadOnlySpan rest = input[(start + needle.Length)..]; + int end = rest.IndexOf(';'); + ReadOnlySpan value = end >= 0 ? rest[..end] : rest; + Console.WriteLine($"key2 = {value}"); + } + // => key2 = beta + // + } + + private static void FormatAndAggregate() + { + // + string[] words = ["The", "quick", "brown", "fox"]; + + // string.Format uses composite formatting: numbered placeholders that + // reference the argument list. Reach for it when the same template + // appears repeatedly with different arguments, such as log messages + // or localized resources where the template lives in a resource file. + string formatted = string.Format("[{0}] {1} {2} {3} {4}!", DateTime.Today.ToShortDateString(), words[0], words[1], words[2], words[3]); + Console.WriteLine(formatted); + + // Enumerable.Aggregate reduces a sequence to a single string by + // applying a lambda to each element in turn. It's the LINQ-friendly + // option when the separator depends on element position or when you + // want to fold extra logic into the accumulation. Each iteration + // allocates a new string, so for plain "join with a separator" + // workloads, string.Join is faster. + string aggregated = words.Aggregate((acc, word) => $"{acc}-{word}"); + Console.WriteLine(aggregated); + // => The-quick-brown-fox + // + } + + private static void CultureDeepDive() + { + // + string esszet = "Sie tanzen auf der Straße."; + string doubleS = "Sie tanzen auf der Strasse."; + + // Linguistic comparison folds 'ß' to "ss" in the invariant culture; + // ordinal comparison sees two distinct code points. + Console.WriteLine($"InvariantCulture equal? {string.Equals(esszet, doubleS, StringComparison.InvariantCulture)}"); + Console.WriteLine($"Ordinal equal? {string.Equals(esszet, doubleS, StringComparison.Ordinal)}"); + + // CompareInfo gives you the underlying linguistic engine and lets you + // pass CompareOptions explicitly. This matches what StringComparison + // uses internally but is the API to reach for when you need to mix + // options like IgnoreSymbols or IgnoreKanaType. + CompareInfo de = CultureInfo.GetCultureInfo("de-DE").CompareInfo; + int order = de.Compare(esszet, doubleS, CompareOptions.None); + Console.WriteLine($"de-DE CompareInfo result: {order}"); + + // StringComparer plugs into Array.Sort, List.Sort, Dictionary, + // HashSet, and other collections that need an IComparer or + // IEqualityComparer. Sort the same input with different + // comparers to see the difference between linguistic and ordinal + // order. The hyphen in "co-op" is weighted close to zero in the + // current culture but sorts before the letters in ordinal order. + string[] linguistic = ["cop", "co-op", "coop"]; + Array.Sort(linguistic, StringComparer.InvariantCulture); + Console.WriteLine($"InvariantCulture order: {string.Join(", ", linguistic)}"); + + string[] ordinal = ["cop", "co-op", "coop"]; + Array.Sort(ordinal, StringComparer.Ordinal); + Console.WriteLine($"Ordinal order: {string.Join(", ", ordinal)}"); + // + } + + private static void StringCreate() + { + // + // string.Create lets you fill a string's character buffer through a + // callback, with no intermediate allocations. Pass the desired length + // and the state value the callback needs; the runtime hands you a + // Span to write into. The result is a normal, immutable string. + char[] body = ['a', 'b', 'c', 'd']; + int length = body.Length + 2; + + string result = string.Create(length, body, static (destination, source) => + { + destination[0] = '0'; + destination[1] = '1'; + source.CopyTo(destination[2..]); + }); + + Console.WriteLine(result); + // => 01abcd + // + } +} diff --git a/docs/csharp/language-reference/builtin-types/snippets/string-operations/string-operations.csproj b/docs/csharp/language-reference/builtin-types/snippets/string-operations/string-operations.csproj new file mode 100644 index 0000000000000..bad583f080c8c --- /dev/null +++ b/docs/csharp/language-reference/builtin-types/snippets/string-operations/string-operations.csproj @@ -0,0 +1,8 @@ + + + Exe + net10.0 + enable + enable + + diff --git a/docs/csharp/language-reference/builtin-types/string-operations.md b/docs/csharp/language-reference/builtin-types/string-operations.md new file mode 100644 index 0000000000000..dc71c7667c52f --- /dev/null +++ b/docs/csharp/language-reference/builtin-types/string-operations.md @@ -0,0 +1,110 @@ +--- +title: "String operations: pattern matching, performance, and span-based search" +description: "Learn how to apply regular-expression patterns to strings, search strings with ReadOnlySpan, and pick the right StringComparison for performance." +ms.topic: reference +ms.date: 05/21/2026 +ai-usage: ai-assisted +--- + +# String operations: pattern matching, performance, and span-based search + +This article covers three string operations: regular-expression pattern matching with , allocation-free search over , and choosing a value for correct, fast comparisons. + +## Find specific text by using regular expressions + +The class searches strings for patterns rather than fixed substrings. The static method takes the input string, a pattern, and optional flags. + +The following example searches each sentence for the word *the* or *their*, case insensitive. The pattern `the(ir)?\s` matches `the` optionally followed by `ir`, then a whitespace character: + +| Pattern | Meaning | +|----------|----------------------------------| +| `the` | match the literal text `the` | +| `(ir)?` | match 0 or 1 occurrence of `ir` | +| `\s` | match a whitespace character | + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="RegexPattern"::: + +## Validate strings against a pattern + +To check whether an entire input matches a shape, anchor the pattern with `^` and `$`. The following example validates that each string is a US-style telephone number: three digits, three digits, four digits, separated by dashes: + +| Pattern | Meaning | +|---------|----------------------------------------| +| `^` | match the beginning of the string | +| `\d{3}` | match exactly three digit characters | +| `-` | match a literal `-` character | +| `\d{4}` | match exactly four digit characters | +| `$` | match the end of the string | + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="RegexValidate"::: + +For the full pattern syntax, see [Regular expression language - quick reference](../../../standard/base-types/regular-expression-language-quick-reference.md). + +## Choose between `string` methods and regular expressions + +`string` methods and `Regex` solve overlapping problems. Prefer `string` methods when the text you're searching for is a literal value, a known prefix or suffix, or a fixed delimiter. They're simpler to read and faster, because they don't pay the cost of compiling and executing a pattern. Reach for `Regex` when the search target is a *shape*, such as alternations, optional groups, repeated character classes, or anchored validation. As a rule of thumb, if you can write the search as one or two `string.Contains` / `StartsWith` / `IndexOf` calls, do so. + +## Search using `ReadOnlySpan` + +When you parse large inputs or run a search on a hot path, the per-call allocations of `string.Substring` and `string.Split` can dominate. `ReadOnlySpan` gives you a view over an existing string (or array, or stack buffer) without copying, and provides span-based equivalents of the common `string` methods, including : + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="SpanSearch"::: + +Span-based search avoids allocations because the slices (`input[start..]`, `rest[..end]`) are simply windows over the original characters. The same approach scales to parsing key-value lists, headers, and other delimited text without ever calling `Substring`. + +## Performance considerations for `StringComparison` + +Most `string` instance methods have overloads that accept a value. Methods such as default to **ordinal**, but and default to **current culture**. This difference matters in two ways: + +- **Speed.** Ordinal comparison is a byte-for-byte test that runs in tight, vectorized loops. Culture-aware comparison consults a sort table, walks combining characters, and applies locale-specific rules. For the same input, it can be an order of magnitude slower. +- **Correctness.** Culture-aware comparison can fold characters that you don't expect (Turkish `i`/`I`, German `ß` to `ss`, ligatures). This behavior is right for sorting names a user sees but wrong for parsing identifiers, paths, or protocol tokens. + +For machine-defined text, such as file names, URLs, HTTP headers, identifiers, configuration keys, pass or explicitly. Reserve culture-aware values for natural-language text shown to users. For comprehensive guidance, see [Best practices for comparing strings in .NET](../../../standard/base-types/best-practices-strings.md). + +## Concatenate with `String.Format` and `Enumerable.Aggregate` + +For most concatenation, `+`, string interpolation, , or is the right tool. and fill more specialized roles: + +- Use `String.Format` when the **template lives somewhere else than the call site** — most often a resource file for localization, a logging template, or any case where the same composite-format string is reused with different arguments. Composite formatting with numbered placeholders (`"{0} {1}"`) lets you swap the format string without recompiling. +- Use `Enumerable.Aggregate` when the **separator or transformation depends on element position**, or when you're already inside a LINQ query and want a single string out. For a straight "join these values with a separator", `string.Join` is faster and clearer because it walks the sequence once and allocates the final string directly. `Aggregate` allocates an intermediate string on each step. + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="format"::: + +## Culture-sensitive comparison in depth + +The basics of choosing a value are covered in [Compare strings](../../fundamentals/strings/common-tasks/compare.md). This section addresses three deeper concerns: the difference between linguistic and ordinal comparison, the .NET 5 switch from NLS to ICU, and the comparer abstractions you pass to collections. + +### Linguistic comparison folds characters + +Linguistic comparison applies the sort weights of a culture's collation table. Two strings that look different can compare equal — for example, the German Esszet `ß` (U+00DF) is treated as equivalent to `ss` under many cultures. Ordinal comparison treats them as the distinct Unicode code points they are: + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="culture-deep"::: + +The exact comparison results in that snippet depend on which globalization library .NET uses on the host. Before .NET 5, .NET on Windows used [National Language Support (NLS)](/windows/win32/intl/national-language-support); other operating systems used ICU. Starting in .NET 5, all platforms default to [International Components for Unicode (ICU)](https://icu.unicode.org/). ICU and NLS don't always agree on the small details — for example, ICU under the invariant culture treats `ß` and `ss` as distinct, while NLS treated them as equal. If your code relied on the old NLS behavior, opt back in with the [`System.Globalization.UseNls` AppContext switch](../../../core/runtime-config/globalization.md). + +### `CompareInfo` and `StringComparer` for collections + + is the underlying engine for culture-aware comparison. Pass flags such as or when a simple value doesn't capture the rule you need. + + wraps a comparison choice into the and interfaces that collections accept. Pass to and when you need a fast, deterministic order; pass when the values are user-visible text. Always use the **same** comparer for sorting and searching — a mismatched pair silently returns wrong results. + +## Allocation-free construction with `String.Create` + +Most ways of building a string allocate intermediate buffers: `+` allocates each result, grows a backing array, and copies its inputs. avoids those copies. You ask for a string of a known length, supply a state value that the callback needs, and the runtime hands the callback a over the final string's character buffer: + +:::code language="csharp" source="snippets/string-operations/Program.cs" id="string-create"::: + +Use this method on a hot path where you know the exact length and want to write each character once. The `static` lambda keeps the callback allocation-free; the `state` parameter (`source` in the example) is the safe way to pass values in, because lambdas given to `string.Create` can't capture variables that would force a closure allocation. + +## See also + +- [Regular expression language — quick reference](../../../standard/base-types/regular-expression-language-quick-reference.md) +- [Best practices for comparing strings in .NET](../../../standard/base-types/best-practices-strings.md) +- [Search strings](../../fundamentals/strings/common-tasks/search.md) +- [Split strings into substrings](../../fundamentals/strings/common-tasks/split.md) +- [Concatenate strings](../../fundamentals/strings/common-tasks/concatenate.md) +- [Modify string contents](../../fundamentals/strings/common-tasks/modify.md) +- [Compare strings](../../fundamentals/strings/common-tasks/compare.md) +- +- +- diff --git a/docs/csharp/language-reference/operators/addition-operator.md b/docs/csharp/language-reference/operators/addition-operator.md index 0c2b32e8afcfd..7ebf9b4055a8f 100644 --- a/docs/csharp/language-reference/operators/addition-operator.md +++ b/docs/csharp/language-reference/operators/addition-operator.md @@ -79,7 +79,7 @@ For more information, see the [Unary plus operator](~/_csharpstandard/standard/e ## See also - [C# operators and expressions](index.md) -- [How to concatenate multiple strings](../../how-to/concatenate-multiple-strings.md) +- [Concatenate strings](../../fundamentals/strings/common-tasks/concatenate.md) - [Events](../../programming-guide/events/index.md) - [Arithmetic operators](arithmetic-operators.md) - [- and -= operators](subtraction-operator.md) diff --git a/docs/csharp/language-reference/operators/equality-operators.md b/docs/csharp/language-reference/operators/equality-operators.md index 8426075434cdd..0fe2f4d41727e 100644 --- a/docs/csharp/language-reference/operators/equality-operators.md +++ b/docs/csharp/language-reference/operators/equality-operators.md @@ -65,7 +65,7 @@ Two [string](../builtin-types/reference-types.md#the-string-type) operands are e :::code language="csharp" source="snippets/shared/EqualityOperators.cs" id="StringEquality"::: -String equality comparisons are case-sensitive ordinal comparisons. For more information about string comparison, see [How to compare strings in C#](../../how-to/compare-strings.md). +String equality comparisons are case-sensitive ordinal comparisons. For more information about string comparison, see [Compare strings in C#](../../fundamentals/strings/common-tasks/compare.md). ### Delegate equality diff --git a/docs/csharp/language-reference/toc.yml b/docs/csharp/language-reference/toc.yml index 29fb29f941bae..9f8589a04fb21 100644 --- a/docs/csharp/language-reference/toc.yml +++ b/docs/csharp/language-reference/toc.yml @@ -65,6 +65,9 @@ items: - name: Nullable reference types href: ./builtin-types/nullable-reference-types.md displayName: "? token, ? symbol" + - name: String operations + displayName: regex, ReadOnlySpan, StringComparison + href: ./builtin-types/string-operations.md - name: Collections and arrays items: - name: Collections diff --git a/docs/csharp/language-reference/tokens/interpolated.md b/docs/csharp/language-reference/tokens/interpolated.md index 61bbc3f68169a..210cb8d4da476 100644 --- a/docs/csharp/language-reference/tokens/interpolated.md +++ b/docs/csharp/language-reference/tokens/interpolated.md @@ -92,7 +92,7 @@ For more information about custom formatting, see the [Custom formatting with IC ## Other resources -If you're new to string interpolation, see the [String interpolation in C#](../../tutorials/string-interpolation.md) tutorial. That tutorial demonstrates how to use interpolated strings to produce formatted strings. +If you're new to string interpolation, see the [String interpolation in C#](../../fundamentals/tutorials/string-interpolation.md) tutorial. That tutorial demonstrates how to use interpolated strings to produce formatted strings. ## Compilation of interpolated strings diff --git a/docs/csharp/programming-guide/strings/index.md b/docs/csharp/programming-guide/strings/index.md index 20d4e754326e8..6d31ab29d7db6 100644 --- a/docs/csharp/programming-guide/strings/index.md +++ b/docs/csharp/programming-guide/strings/index.md @@ -34,7 +34,7 @@ Because a string "modification" is actually a new string creation, you must use :::code language="csharp" source="./snippets/Declarations.cs" id="ModifyIsCopy"::: -For more information about how to create new strings that are based on modifications such as search and replace operations on the original string, see [How to modify string contents](../../how-to/modify-string-contents.md). +For more information about how to create new strings that are based on modifications such as search and replace operations on the original string, see [Modify string contents](../../fundamentals/strings/common-tasks/modify.md). ## Quoted string literals @@ -107,7 +107,7 @@ A format string is a string whose contents are determined dynamically at run tim ### String interpolation -You declare [*Interpolated strings*](../../language-reference/tokens/interpolated.md) with the `$` special character. An interpolated string includes interpolated expressions in braces. If you're new to string interpolation, see the [String interpolation - C# tutorial](../../tutorials/string-interpolation.md) for several examples. +You declare [*Interpolated strings*](../../language-reference/tokens/interpolated.md) with the `$` special character. An interpolated string includes interpolated expressions in braces. If you're new to string interpolation, see the [String interpolation - C# tutorial](../../fundamentals/tutorials/string-interpolation.md) for several examples. Use string interpolation to improve the readability and maintainability of your code. String interpolation achieves the same results as the `String.Format` method, but is easier to use and improves inline clarity. @@ -137,7 +137,7 @@ For more information, see [Composite formatting in .NET](../../../standard/base- ## Substrings -A substring is any sequence of characters that is contained in a string. Use the method to create a new string from a part of the original string. You can search for one or more occurrences of a substring by using the method. Use the method to replace all occurrences of a specified substring with a new string. Like the method, actually returns a new string and doesn't modify the original string. For more information, see [How to search strings](../../how-to/search-strings.md) and [How to modify string contents](../../how-to/modify-string-contents.md). +A substring is any sequence of characters that is contained in a string. Use the method to create a new string from a part of the original string. You can search for one or more occurrences of a substring by using the method. Use the method to replace all occurrences of a specified substring with a new string. Like the method, actually returns a new string and doesn't modify the original string. For more information, see [Search strings in C#](../../fundamentals/strings/common-tasks/search.md) and [Modify string contents](../../fundamentals/strings/common-tasks/modify.md). :::code language="csharp" source="./snippets/StringCharacters.cs" id="Substrings"::: @@ -181,11 +181,11 @@ Because the type implements method to parse strings. -- [How to search strings](../../how-to/search-strings.md): Explains how to use search for specific text or patterns in strings. +- [Modify string contents](../../fundamentals/strings/common-tasks/modify.md): Illustrates techniques to transform strings and modify the contents of strings. +- [Compare strings](../../fundamentals/strings/common-tasks/compare.md): Shows how to perform ordinal and culture specific comparisons of strings. +- [Concatenate strings](../../fundamentals/strings/common-tasks/concatenate.md): Demonstrates various ways to join multiple strings into one. +- [Split strings into substrings in C#](../../fundamentals/strings/common-tasks/split.md): Contains code examples that illustrate how to use the method to parse strings. +- [Search strings in C#](../../fundamentals/strings/common-tasks/search.md): Explains how to search for specific text or patterns in strings. - [How to determine whether a string represents a numeric value](./how-to-determine-whether-a-string-represents-a-numeric-value.md): Shows how to safely parse a string to see whether it has a valid numeric value. - [String interpolation](../../language-reference/tokens/interpolated.md): Describes the string interpolation feature that provides a convenient syntax to format strings. - [Using the StringBuilder class in .NET](../../../standard/base-types/stringbuilder.md) diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml index f122ed37af35b..01c11bb9c130c 100644 --- a/docs/csharp/toc.yml +++ b/docs/csharp/toc.yml @@ -73,7 +73,6 @@ items: href: fundamentals/types/delegates-lambdas.md - name: Anonymous types href: programming-guide/classes-and-structs/anonymous-types.md - # TODO: Delegates, lambdas and events - name: Null safety items: - name: Overview @@ -82,20 +81,34 @@ items: href: fundamentals/null-safety/nullable-value-types.md - name: Nullable reference types href: fundamentals/null-safety/nullable-reference-types.md - - name: Resolve nullable warnings - href: fundamentals/null-safety/resolve-warnings.md - name: Null operators href: fundamentals/null-safety/null-operators.md - - name: "Tutorial: Express your design intent with nullable reference types" - href: fundamentals/tutorials/nullable-reference-types.md + - name: Common tasks + items: + - name: Resolve nullable warnings + href: fundamentals/null-safety/common-tasks/resolve-warnings.md - name: Strings items: - name: Overview href: fundamentals/strings/index.md - name: Raw string literals href: fundamentals/strings/raw-string-literals.md + - name: String interpolation + href: fundamentals/strings/interpolation.md - name: nameof operator href: fundamentals/strings/nameof.md + - name: Common tasks + items: + - name: Search strings + href: fundamentals/strings/common-tasks/search.md + - name: Split strings into substrings + href: fundamentals/strings/common-tasks/split.md + - name: Concatenate strings + href: fundamentals/strings/common-tasks/concatenate.md + - name: Modify string contents + href: fundamentals/strings/common-tasks/modify.md + - name: Compare strings + href: fundamentals/strings/common-tasks/compare.md - name: Object-oriented programming items: - name: Classes, structs, and records @@ -156,6 +169,8 @@ items: # TODO: Classes and objects (interfaces and classes) # TODO: Generics (methods and classes) # TODO: Fundamentals of using lambdas + - name: Express your design intent with nullable reference types + href: fundamentals/tutorials/nullable-reference-types.md - name: Introduction to classes href: fundamentals/tutorials/classes.md - name: Object-oriented C# @@ -175,6 +190,8 @@ items: href: fundamentals/tutorials/pattern-matching.md - name: Use record types href: fundamentals/tutorials/records.md + - name: "Tutorial: String interpolation" + href: fundamentals/tutorials/string-interpolation.md # separating data and algorithms # Data transformations ## TODO: Replace with a tutorial (include async exceptions) @@ -228,8 +245,6 @@ items: href: tutorials/ranges-indexes.md - name: Explore patterns in objects href: tutorials/patterns-objects.md - - name: String interpolation - href: tutorials/string-interpolation.md - name: Console Application href: tutorials/console-teleprompter.md - name: REST Client @@ -341,16 +356,6 @@ items: - name: Article index displayName: how to's href: how-to/index.md - - name: Split strings into substrings - href: how-to/parse-strings-using-split.md - - name: Concatenate strings - href: how-to/concatenate-multiple-strings.md - - name: Search strings - href: how-to/search-strings.md - - name: Modify string contents - href: how-to/modify-string-contents.md - - name: Compare strings - href: how-to/compare-strings.md - name: "How to catch a non-CLS exception" href: how-to/how-to-catch-a-non-cls-exception.md - name: Advanced topics diff --git a/docs/framework/performance/performance-tips.md b/docs/framework/performance/performance-tips.md index c59dc20167051..f5fc39b9b66aa 100644 --- a/docs/framework/performance/performance-tips.md +++ b/docs/framework/performance/performance-tips.md @@ -21,7 +21,7 @@ The term *performance* generally refers to the execution speed of a program. You ## Strings - When you concatenate a large number of string variables, for example in a tight loop, use instead of the C# [+ operator](../../csharp/language-reference/operators/addition-operator.md) or the Visual Basic [Concatenation Operators](../../visual-basic/language-reference/operators/concatenation-operators.md). For more information, see [How to concatenate multiple strings](../../csharp/how-to/concatenate-multiple-strings.md) and [Concatenation Operators in Visual Basic](../../visual-basic/programming-guide/language-features/operators-and-expressions/concatenation-operators.md). + When you concatenate a large number of string variables, for example in a tight loop, use instead of the C# [+ operator](../../csharp/language-reference/operators/addition-operator.md) or the Visual Basic [Concatenation Operators](../../visual-basic/language-reference/operators/concatenation-operators.md). For more information, see [Concatenate strings in C#](../../csharp/fundamentals/strings/common-tasks/concatenate.md) and [Concatenation Operators in Visual Basic](../../visual-basic/programming-guide/language-features/operators-and-expressions/concatenation-operators.md). ## Finalizers diff --git a/docs/fundamentals/code-analysis/quality-rules/ca1305.md b/docs/fundamentals/code-analysis/quality-rules/ca1305.md index 22cfa1c57a619..1ecdd5a2c69b6 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca1305.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca1305.md @@ -51,7 +51,7 @@ Even if the default behavior of the overloaded member is appropriate for your ne ## How to fix violations -To fix a violation of this rule, use the overload that takes an argument. Or, to use the invariant culture, use a [C# interpolated string](../../../csharp/tutorials/string-interpolation.md) and pass it to along with , for example: +To fix a violation of this rule, use the overload that takes an argument. Or, to use the invariant culture, use a [C# interpolated string](../../../csharp/fundamentals/tutorials/string-interpolation.md) and pass it to along with , for example: ```csharp string.Create(CultureInfo.InvariantCulture, $"{major}.{minor}.{build}.{revision}"); diff --git a/docs/standard/base-types/best-practices-strings.md b/docs/standard/base-types/best-practices-strings.md index 17bd7ddc5015b..1f606e0b266f7 100644 --- a/docs/standard/base-types/best-practices-strings.md +++ b/docs/standard/base-types/best-practices-strings.md @@ -453,4 +453,4 @@ If you migrate an application from .NET Framework to .NET and rely on legacy NLS - [Globalization in .NET apps](../../core/extensions/globalization.md) - [.NET globalization and ICU](../../core/extensions/globalization-icu.md) -- [How to compare strings in C#](../../csharp/how-to/compare-strings.md) +- [Compare strings in C#](../../csharp/fundamentals/strings/common-tasks/compare.md) diff --git a/docs/standard/base-types/divide-up-strings.md b/docs/standard/base-types/divide-up-strings.md index 295edaede453e..b2003aef215c8 100644 --- a/docs/standard/base-types/divide-up-strings.md +++ b/docs/standard/base-types/divide-up-strings.md @@ -132,5 +132,5 @@ The next example uses the index-from-end operator to remove a file extension (th ## See also - [.NET regular expressions](regular-expressions.md) -- [How to parse strings using String.Split in C#](../../csharp/how-to/parse-strings-using-split.md) +- [Split strings into substrings in C#](../../csharp/fundamentals/strings/common-tasks/split.md) - [Indices and ranges (C# guide)](../../csharp/tutorials/ranges-indexes.md)