diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
index cd3b49725826e..f248575e467bb 100644
--- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
+++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzers.projitems
@@ -122,6 +122,7 @@
+
diff --git a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx
index 1574a4e49a86a..4ebe1d626a4ea 100644
--- a/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx
+++ b/src/Analyzers/CSharp/Analyzers/CSharpAnalyzersResources.resx
@@ -305,6 +305,12 @@
'new' expression can be simplified
+
+ Lambda expression can be simplified
+
+
+ Use implicitly typed lambda
+
Discard can be removed
diff --git a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
index a2fc11e8f70c3..0e5b54eb44ac0 100644
--- a/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
+++ b/src/Analyzers/CSharp/Analyzers/CodeStyle/CSharpAnalyzerOptionsProvider.cs
@@ -55,6 +55,7 @@ internal CSharpSimplifierOptions GetSimplifierOptions()
public CodeStyleOption2 PreferPatternMatchingOverIsWithCastCheck => GetOption(CSharpCodeStyleOptions.PreferPatternMatchingOverIsWithCastCheck);
public CodeStyleOption2 PreferNotPattern => GetOption(CSharpCodeStyleOptions.PreferNotPattern);
public CodeStyleOption2 PreferExtendedPropertyPattern => GetOption(CSharpCodeStyleOptions.PreferExtendedPropertyPattern);
+ public CodeStyleOption2 PreferImplicitlyTypedLambdaExpression => GetOption(CSharpCodeStyleOptions.PreferImplicitlyTypedLambdaExpression);
public CodeStyleOption2 PreferInlinedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferInlinedVariableDeclaration);
public CodeStyleOption2 PreferDeconstructedVariableDeclaration => GetOption(CSharpCodeStyleOptions.PreferDeconstructedVariableDeclaration);
public CodeStyleOption2 PreferIndexOperator => GetOption(CSharpCodeStyleOptions.PreferIndexOperator);
diff --git a/src/Analyzers/CSharp/Analyzers/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer.cs
new file mode 100644
index 0000000000000..747bd949e2fca
--- /dev/null
+++ b/src/Analyzers/CSharp/Analyzers/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer.cs
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Linq;
+using System.Threading;
+using Microsoft.CodeAnalysis.CodeStyle;
+using Microsoft.CodeAnalysis.CSharp.CodeStyle;
+using Microsoft.CodeAnalysis.CSharp.Extensions;
+using Microsoft.CodeAnalysis.CSharp.Shared.Extensions;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.CSharp.Utilities;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Shared.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp.UseImplicitlyTypedLambdaExpression;
+
+using static SyntaxFactory;
+
+[DiagnosticAnalyzer(LanguageNames.CSharp)]
+internal sealed class CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer()
+ : AbstractBuiltInCodeStyleDiagnosticAnalyzer(IDEDiagnosticIds.UseImplicitlyTypedLambdaExpressionDiagnosticId,
+ EnforceOnBuildValues.UseImplicitObjectCreation,
+ CSharpCodeStyleOptions.PreferImplicitlyTypedLambdaExpression,
+ new LocalizableResourceString(nameof(CSharpAnalyzersResources.Use_implicitly_typed_lambda), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)),
+ new LocalizableResourceString(nameof(CSharpAnalyzersResources.Lambda_expression_can_be_simplified), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)))
+{
+ public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
+ => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
+
+ protected override void InitializeWorker(AnalysisContext context)
+ => context.RegisterSyntaxNodeAction(AnalyzeIfEnabled,
+ SyntaxKind.ParenthesizedLambdaExpression);
+
+ private void AnalyzeIfEnabled(SyntaxNodeAnalysisContext context)
+ {
+ var cancellationToken = context.CancellationToken;
+ var analyzerOptions = context.Options;
+ var semanticModel = context.SemanticModel;
+ var option = analyzerOptions.GetCSharpAnalyzerOptions(semanticModel.SyntaxTree).PreferImplicitlyTypedLambdaExpression;
+ if (!option.Value || ShouldSkipAnalysis(context, option.Notification))
+ return;
+
+ var explicitLambda = (ParenthesizedLambdaExpressionSyntax)context.Node;
+ if (!Analyze(semanticModel, explicitLambda, cancellationToken))
+ return;
+
+ context.ReportDiagnostic(DiagnosticHelper.Create(
+ Descriptor,
+ explicitLambda.ParameterList.OpenParenToken.GetLocation(),
+ option.Notification,
+ context.Options,
+ [explicitLambda.GetLocation()],
+ properties: null));
+ }
+
+ public static bool Analyze(
+ SemanticModel semanticModel,
+ ParenthesizedLambdaExpressionSyntax explicitLambda,
+ CancellationToken cancellationToken)
+ {
+ // If the lambda has an explicit return type, then do not offer the feature. Explicit return types are used to
+ // provide full semantic information to the compiler so it does not need to perform speculative lambda binding.
+ // Removing may cause code compilation performance to regress.
+ if (explicitLambda.ReturnType != null)
+ return false;
+
+ // Needs to have at least one parameter, all parameters need to have a provided type, and no parameters can have a
+ // default value provided.
+ if (explicitLambda.ParameterList.Parameters.Count == 0 ||
+ explicitLambda.ParameterList.Parameters.Any(p => p.Type is null || p.Default != null))
+ {
+ return false;
+ }
+
+ // Prior to C# 14, implicitly typed lambdas can't have modifiers on parameters.
+ var languageVersion = semanticModel.Compilation.LanguageVersion();
+ if (!languageVersion.IsCSharp14OrAbove() && explicitLambda.ParameterList.Parameters.Any(p => p.Modifiers.Count > 0))
+ return false;
+
+ var implicitLambda = ConvertToImplicitlyTypedLambda(explicitLambda);
+
+ var analyzer = new SpeculationAnalyzer(
+ explicitLambda, implicitLambda, semanticModel, cancellationToken);
+ if (analyzer.ReplacementChangesSemantics())
+ return false;
+
+ if (semanticModel.GetSymbolInfo(explicitLambda, cancellationToken).Symbol is not IMethodSymbol explicitLambdaMethod ||
+ analyzer.SpeculativeSemanticModel.GetSymbolInfo(analyzer.ReplacedExpression, cancellationToken).Symbol is not IMethodSymbol implicitLambdaMethod)
+ {
+ return false;
+ }
+
+ if (!SignatureComparer.Instance.HaveSameSignature(explicitLambdaMethod, implicitLambdaMethod, caseSensitive: true))
+ return false;
+
+ return true;
+ }
+
+ public static LambdaExpressionSyntax ConvertToImplicitlyTypedLambda(ParenthesizedLambdaExpressionSyntax explicitLambda)
+ {
+ var implicitLambda = explicitLambda.ReplaceNodes(
+ explicitLambda.ParameterList.Parameters,
+ (parameter, _) => RemoveParamsModifier(
+ parameter.WithType(null)
+ .WithIdentifier(parameter.Identifier.WithPrependedLeadingTrivia(parameter.Type!.GetLeadingTrivia()))));
+
+ // If the lambda only has one parameter, then convert it to the non-parenthesized form.
+ if (implicitLambda.ParameterList.Parameters is not ([{ AttributeLists.Count: 0, Modifiers.Count: 0 } parameter]))
+ return implicitLambda;
+
+ return SimpleLambdaExpression(
+ explicitLambda.AttributeLists,
+ explicitLambda.Modifiers,
+ parameter.WithTriviaFrom(explicitLambda.ParameterList),
+ explicitLambda.Block,
+ explicitLambda.ExpressionBody);
+ }
+
+ private static ParameterSyntax RemoveParamsModifier(ParameterSyntax parameter)
+ {
+ // Implicitly typed lambdas aren't ever allowed to have the 'params' modifier.
+ var paramsModifierIndex = parameter.Modifiers.IndexOf(SyntaxKind.ParamsKeyword);
+ return paramsModifierIndex >= 0 ? parameter.WithModifiers(parameter.Modifiers.RemoveAt(paramsModifierIndex)) : parameter;
+ }
+}
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf
index fd92a148a5131..a9944b6452e98 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.cs.xlf
@@ -97,6 +97,11 @@
Výraz lambda je možné odebrat
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Nastavit anonymní funkci jako statickou
@@ -352,6 +357,11 @@
Použít implicitní typ
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Použít operátor indexu
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf
index 62aefa1dfa65f..def7a379da0d0 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.de.xlf
@@ -97,6 +97,11 @@
Lambdaausdruck kann entfernt werden
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Anonyme Funktion statisch machen
@@ -352,6 +357,11 @@
Impliziten Typ verwenden
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Indexoperator verwenden
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf
index 1c664a907efdc..adc7b18f02ee9 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.es.xlf
@@ -97,6 +97,11 @@
Se puede quitar la expresión lambda
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Hacer que la función anónima sea estática
@@ -352,6 +357,11 @@
Usar un tipo implícito
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Usar operador de índice
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf
index 3104c437e6a0d..7d1240420e11c 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.fr.xlf
@@ -97,6 +97,11 @@
L’expression lambda peut être supprimée.
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Rendre la fonction anonyme statique
@@ -352,6 +357,11 @@
Utiliser un type implicite
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Utiliser l'opérateur d'index
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf
index c140510bbdf48..2e801e924b71b 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.it.xlf
@@ -97,6 +97,11 @@
L'espressione lambda può essere rimossa
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Rendere statica la funzione anonima
@@ -352,6 +357,11 @@
Usa il tipo implicito
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Usa operatore di indice
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf
index 4b66e8433b16d..fe0ed3e9530ab 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ja.xlf
@@ -97,6 +97,11 @@
ラムダ式を削除できます
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
匿名関数を静的にする
@@ -352,6 +357,11 @@
暗黙的な型の使用
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
インデックス演算子を使用
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf
index b31a57f0641d0..0d32ece7ae2f0 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ko.xlf
@@ -97,6 +97,11 @@
람다 식을 제거할 수 있습니다.
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
익명 함수를 정적으로 설정
@@ -352,6 +357,11 @@
암시적 형식 사용
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
인덱스 연산자 사용
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf
index 72bec10276155..ab3c71626dbc1 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pl.xlf
@@ -97,6 +97,11 @@
Wyrażenie lambda można usunąć
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Ustaw funkcję anonimową jako statyczną
@@ -352,6 +357,11 @@
Użyj niejawnego typu
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Użyj operatora indeksu
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf
index 0b0f9af906709..2f3471d9fc516 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.pt-BR.xlf
@@ -97,6 +97,11 @@
A expressão lambda pode ser removida
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Tornar a função anônima estática
@@ -352,6 +357,11 @@
Usar o tipo implícito
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Usar operador de índice
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf
index 2498b23b3f3be..6e903f2745ff0 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.ru.xlf
@@ -97,6 +97,11 @@
Лямбда-выражение можно удалить
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Сделать анонимную функцию статической
@@ -352,6 +357,11 @@
Использование неявного типа
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Использовать оператор индекса
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf
index 973bf1a1f2495..ab3d21c5b60a0 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.tr.xlf
@@ -97,6 +97,11 @@
Lambda ifadesi kaldırılabilir
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
Anonim işlevi statik hale getir
@@ -352,6 +357,11 @@
Örtük tür kullanma
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
Dizin işleci kullan
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf
index e3251991e3d76..7923c12961cd7 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hans.xlf
@@ -97,6 +97,11 @@
可以删除 Lambda 表达式
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
使匿名函数成为静态函数
@@ -352,6 +357,11 @@
使用隐式类型
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
使用索引运算符
diff --git a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf
index 81083e318ef16..45161bed0f596 100644
--- a/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf
+++ b/src/Analyzers/CSharp/Analyzers/xlf/CSharpAnalyzersResources.zh-Hant.xlf
@@ -97,6 +97,11 @@
可移除 Lambda 運算式
+
+ Lambda expression can be simplified
+ Lambda expression can be simplified
+
+
Make anonymous function static
讓匿名函式成為靜態
@@ -352,6 +357,11 @@
使用隱含類型
+
+ Use implicitly typed lambda
+ Use implicitly typed lambda
+
+
Use index operator
使用索引運算子
diff --git a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
index 9ffe839f76f3e..4df925fb0816e 100644
--- a/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
+++ b/src/Analyzers/CSharp/CodeFixes/CSharpCodeFixes.projitems
@@ -111,6 +111,7 @@
+
diff --git a/src/Analyzers/CSharp/CodeFixes/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitObjectCreationCodeFixProvider.cs b/src/Analyzers/CSharp/CodeFixes/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitObjectCreationCodeFixProvider.cs
new file mode 100644
index 0000000000000..c7e1193eedf8b
--- /dev/null
+++ b/src/Analyzers/CSharp/CodeFixes/UseImplicitlyTypedLambdaExpression/CSharpUseImplicitObjectCreationCodeFixProvider.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Immutable;
+using System.Composition;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp.Simplification;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Editing;
+using Microsoft.CodeAnalysis.Host.Mef;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Simplification;
+using Roslyn.Utilities;
+
+namespace Microsoft.CodeAnalysis.CSharp.UseImplicitlyTypedLambdaExpression;
+
+using static CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer;
+
+[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.UseImplicitlyTypedLambdaExpression), Shared]
+[method: ImportingConstructor]
+[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
+internal sealed class CSharpUseImplicitlyTypedLambdaExpressionCodeFixProvider() : SyntaxEditorBasedCodeFixProvider
+{
+ public override ImmutableArray FixableDiagnosticIds
+ => [IDEDiagnosticIds.UseImplicitlyTypedLambdaExpressionDiagnosticId];
+
+ public override Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ RegisterCodeFix(context, CSharpAnalyzersResources.Use_implicitly_typed_lambda, nameof(CSharpAnalyzersResources.Use_implicitly_typed_lambda));
+ return Task.CompletedTask;
+ }
+
+ protected override async Task FixAllAsync(
+ Document document, ImmutableArray diagnostics,
+ SyntaxEditor editor, CancellationToken cancellationToken)
+ {
+ // process from inside->out so that outer rewrites see the effects of inner changes.
+ var nodes = diagnostics
+ .OrderBy(d => d.Location.SourceSpan.End)
+ .SelectAsArray(d => (ParenthesizedLambdaExpressionSyntax)d.AdditionalLocations[0].FindNode(getInnermostNodeForTie: true, cancellationToken));
+
+ var options = (CSharpSimplifierOptions)await document.GetSimplifierOptionsAsync(
+ CSharpSimplification.Instance, cancellationToken).ConfigureAwait(false);
+
+ // Bulk apply these, except at the expression level. One fix at the expression level may prevent another fix
+ // from being valid.
+ await editor.ApplyExpressionLevelSemanticEditsAsync(
+ document,
+ nodes,
+ (semanticModel, node) => Analyze(semanticModel, node, cancellationToken),
+ (semanticModel, root, node) => FixOne(root, node),
+ cancellationToken).ConfigureAwait(false);
+ }
+
+ private static SyntaxNode FixOne(SyntaxNode root, ParenthesizedLambdaExpressionSyntax explicitLambda)
+ => root.ReplaceNode(explicitLambda, ConvertToImplicitlyTypedLambda(explicitLambda));
+}
diff --git a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems
index ffbb78e02db66..373da8195efa9 100644
--- a/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems
+++ b/src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems
@@ -158,6 +158,7 @@
+
@@ -201,5 +202,6 @@
+
\ No newline at end of file
diff --git a/src/Analyzers/CSharp/Tests/UseImplicitlyTypedLambdaExpression/UseImplicitlyTypedLambdaExpressionTests.cs b/src/Analyzers/CSharp/Tests/UseImplicitlyTypedLambdaExpression/UseImplicitlyTypedLambdaExpressionTests.cs
new file mode 100644
index 0000000000000..437372cd52917
--- /dev/null
+++ b/src/Analyzers/CSharp/Tests/UseImplicitlyTypedLambdaExpression/UseImplicitlyTypedLambdaExpressionTests.cs
@@ -0,0 +1,515 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.UseImplicitlyTypedLambdaExpression;
+using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
+using Microsoft.CodeAnalysis.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.UseImplicitlyTypedLambdaExpression;
+
+using VerifyCS = CSharpCodeFixVerifier<
+ CSharpUseImplicitlyTypedLambdaExpressionDiagnosticAnalyzer,
+ CSharpUseImplicitlyTypedLambdaExpressionCodeFixProvider>;
+
+[Trait(Traits.Feature, Traits.Features.CodeActionsUseImplicitObjectCreation)]
+public sealed class UseImplicitlyTypedLambdaExpressionTests
+{
+ private static readonly LanguageVersion CSharp14 = LanguageVersion.Preview;
+
+ [Fact]
+ public async Task TestAssignedToObject()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ object a = (int x) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestCastedToDelegate()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ object a = (Delegate)((int x) => { });
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestCastedToObject()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ object a = (object)((int x) => { });
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestAssignedToDelegate()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Delegate a = (int x) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestAssignedToVar()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ var a = (int x) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestAssignedToStronglyTypedDelegate()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = [|(|]int x) => { };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = x => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestExplicitReturnType()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = void (int x) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestWithDefaultVAlue()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = (int x = 1) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestCastToStronglyTypedDelegate()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Delegate a = (Action)([|(|]int x) => { });
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Delegate a = (Action)(x => { });
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestCreationOfStronglyTypedDelegate()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Delegate a = new Action([|(|]int x) => { });
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Delegate a = new Action(x => { });
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestArgument()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M(Action action)
+ {
+ M([|(|]int x) => { });
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M(Action action)
+ {
+ M(x => { });
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestOverloadResolution()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M(Action action)
+ {
+ M((int x) => { });
+ }
+
+ void M(Action action)
+ {
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestModifier_CSharp13()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ delegate void D(ref int i);
+
+ class C
+ {
+ void M()
+ {
+ D d = (ref int i) => { };
+ }
+ }
+ """,
+ LanguageVersion = LanguageVersion.CSharp13,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestModifier_CSharp14()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ delegate void D(ref int i);
+
+ class C
+ {
+ void M()
+ {
+ D d = [|(|]ref int i) => { };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ delegate void D(ref int i);
+
+ class C
+ {
+ void M()
+ {
+ D d = [|(|]ref i) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestNested()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = [|(|]int x) =>
+ {
+ Action b = [|(|]int y) => { };
+ };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a = x =>
+ {
+ Action b = y => { };
+ };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestParams()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ delegate void D(params int[] x);
+
+ class C
+ {
+ void M()
+ {
+ D d = [|(|]params int[] x) => { };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ delegate void D(params int[] x);
+
+ class C
+ {
+ void M()
+ {
+ D d = x => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestMultiLine()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a =
+ [|(|]int x,
+ int y,
+ int z) => { };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class C
+ {
+ void M()
+ {
+ Action a =
+ (x,
+ y,
+ z) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+
+ [Fact]
+ public async Task TestAttribute()
+ {
+ await new VerifyCS.Test
+ {
+ TestCode = """
+ using System;
+
+ class XAttribute : Attribute
+ {
+ }
+
+ class C
+ {
+ void M()
+ {
+ Action d = [|(|][X] int i) => { };
+ }
+ }
+ """,
+ FixedCode = """
+ using System;
+
+ class XAttribute : Attribute
+ {
+ }
+
+ class C
+ {
+ void M()
+ {
+ Action d = [|(|][X] i) => { };
+ }
+ }
+ """,
+ LanguageVersion = CSharp14,
+ }.RunAsync();
+ }
+}
diff --git a/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs b/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs
index d928c1230975e..8f49df52e2dfb 100644
--- a/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs
+++ b/src/Analyzers/Core/Analyzers/EnforceOnBuildValues.cs
@@ -100,6 +100,7 @@ internal static class EnforceOnBuildValues
public const EnforceOnBuild MakeAnonymousFunctionStatic = /*IDE0320*/ EnforceOnBuild.Recommended;
public const EnforceOnBuild UseSystemThreadingLock = /*IDE0330*/ EnforceOnBuild.Recommended;
public const EnforceOnBuild UseUnboundGenericTypeInNameOf = /*IDE0340*/ EnforceOnBuild.Recommended;
+ public const EnforceOnBuild UseImplicitlyTypedLambdaExpression = /*IDE0350*/ EnforceOnBuild.Recommended;
/* EnforceOnBuild.WhenExplicitlyEnabled */
public const EnforceOnBuild RemoveUnnecessaryCast = /*IDE0004*/ EnforceOnBuild.WhenExplicitlyEnabled; // TODO: Move to 'Recommended' OR 'HighlyRecommended' bucket once performance problems are addressed: https://github.com/dotnet/roslyn/issues/43304
diff --git a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs
index 40a3080d0299f..0332f81299acd 100644
--- a/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs
+++ b/src/Analyzers/Core/Analyzers/IDEDiagnosticIds.cs
@@ -207,6 +207,8 @@ internal static class IDEDiagnosticIds
public const string UseUnboundGenericTypeInNameOfDiagnosticId = "IDE0340";
+ public const string UseImplicitlyTypedLambdaExpressionDiagnosticId = "IDE0350";
+
// Analyzer error Ids
public const string AnalyzerChangedId = "IDE1001";
public const string AnalyzerDependencyConflictId = "IDE1002";
diff --git a/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs b/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs
index 9f974b3e2bdb2..dc931b6b22c5f 100644
--- a/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs
+++ b/src/Analyzers/Core/CodeFixes/PredefinedCodeFixProviderNames.cs
@@ -154,6 +154,7 @@ internal static class PredefinedCodeFixProviderNames
public const string UseExpressionBody = nameof(UseExpressionBody);
public const string UseExpressionBodyForLambda = nameof(UseExpressionBodyForLambda);
public const string UseImplicitObjectCreation = nameof(UseImplicitObjectCreation);
+ public const string UseImplicitlyTypedLambdaExpression = nameof(UseImplicitlyTypedLambdaExpression);
public const string UseImplicitType = nameof(UseImplicitType);
public const string UseIndexOperator = nameof(UseIndexOperator);
public const string UseInferredMemberName = nameof(UseInferredMemberName);
diff --git a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs
index 8ddaef7086ff7..36980fea3c6c2 100644
--- a/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs
+++ b/src/EditorFeatures/Test/Diagnostics/IDEDiagnosticIDConfigurationTests.cs
@@ -493,6 +493,9 @@ public void CSharp_VerifyIDEDiagnosticSeveritiesAreConfigurable()
# IDE0340
dotnet_diagnostic.IDE0340.severity = %value%
+
+ # IDE0350
+ dotnet_diagnostic.IDE0350.severity = %value%
# IDE1005
dotnet_diagnostic.IDE1005.severity = %value%
@@ -912,6 +915,7 @@ public void CSharp_VerifyIDECodeStyleOptionsAreConfigurable()
("IDE0320", "csharp_prefer_static_anonymous_function", "true"),
("IDE0330", "csharp_prefer_system_threading_lock", "true"),
("IDE0340", "csharp_style_prefer_unbound_generic_type_in_nameof", "true"),
+ ("IDE0350", "csharp_style_prefer_implicitly_typed_lambda_expression", "true"),
("IDE1005", "csharp_style_conditional_delegate_call", "true"),
("IDE1006", null, null),
("IDE1007", null, null),
diff --git a/src/Features/RulesMissingDocumentation.md b/src/Features/RulesMissingDocumentation.md
index 4828131b75ff9..07536d5ee0624 100644
--- a/src/Features/RulesMissingDocumentation.md
+++ b/src/Features/RulesMissingDocumentation.md
@@ -16,6 +16,7 @@ IDE0306 | | Make anonymous function static |
IDE0330 | | Use 'System.Threading.Lock' |
IDE0340 | | Use unbound generic type |
+IDE0350 | | Use implicitly typed lambda |
IDE1007 | | |
IDE2000 | | Avoid multiple blank lines |
IDE2001 | | Embedded statements must be on their own line |
diff --git a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx
index 1294054572933..02364e09a1e84 100644
--- a/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx
+++ b/src/VisualStudio/CSharp/Impl/CSharpVSResources.resx
@@ -557,4 +557,7 @@
Cancel (Escape)
+
+ Prefer implicitly typed lambda expression
+
\ No newline at end of file
diff --git a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
index 90b03e02d0973..799d1327ba962 100644
--- a/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
+++ b/src/VisualStudio/CSharp/Impl/EditorConfigSettings/DataProvider/CodeStyle/CSharpCodeStyleSettingsProvider.cs
@@ -115,6 +115,7 @@ private static IEnumerable GetExpressionCodeStyleOptions(Tiere
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferIndexOperator, ServicesVSResources.Prefer_index_operator, options, updater);
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferRangeOperator, ServicesVSResources.Prefer_range_operator, options, updater);
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.ImplicitObjectCreationWhenTypeIsApparent, CSharpVSResources.Prefer_implicit_object_creation_when_type_is_apparent, options, updater);
+ yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferImplicitlyTypedLambdaExpression, CSharpVSResources.Prefer_implicitly_typed_lambda_expression, options, updater);
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferTupleSwap, ServicesVSResources.Prefer_tuple_swap, options, updater);
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferUnboundGenericTypeInNameOf, ServicesVSResources.Prefer_unbound_generic_type_in_nameof, options, updater);
yield return CodeStyleSetting.Create(CSharpCodeStyleOptions.PreferUtf8StringLiterals, ServicesVSResources.Prefer_Utf8_string_literals, options, updater);
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf
index e1c4cc4776bb8..2afd0b93c4f35 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.cs.xlf
@@ -142,6 +142,11 @@
Upřednostňovat implicitní vytvoření objektu, pokud je typ zřejmý
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Upřednostňovat porovnávání vzorů
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf
index dd26b273bb22c..84959e8ae705f 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.de.xlf
@@ -142,6 +142,11 @@
Implizite Objekterstellung bevorzugen, wenn der Typ offensichtlich ist
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Musterabgleich bevorzugen
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf
index f1a6af39bdd90..57551e43d2c1d 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.es.xlf
@@ -142,6 +142,11 @@
Preferir la creación implícita de objetos cuando el tipo sea aparente
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Preferir coincidencia de patrones
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf
index 1c01ddbc6d47e..f81239c73f579 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.fr.xlf
@@ -142,6 +142,11 @@
Préférer la création d'objets implicites quand le type est apparent
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Préférer les critères spéciaux
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf
index cb563ea25c5b9..88e4ba0fb263e 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.it.xlf
@@ -142,6 +142,11 @@
Preferisci la creazione implicita di oggetti quando il tipo è apparente
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Preferisci i criteri di ricerca
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf
index 4ddb98d5b905e..0f28b50458bbf 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ja.xlf
@@ -142,6 +142,11 @@
型が明白な場合に暗黙的なオブジェクトの作成を優先する
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
パターン マッチングを優先する
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf
index 4869b58f2b810..0b768384a3d5b 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ko.xlf
@@ -142,6 +142,11 @@
형식이 명백한 경우 암시적 개체 만들기 선호
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
패턴 일치 선호
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf
index 3c8a0c83b66b0..f11c52cd3f1ce 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pl.xlf
@@ -142,6 +142,11 @@
Preferuj niejawne tworzenie obiektu, gdy typ jest oczywisty
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Preferuj dopasowywanie do wzorca
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf
index 87455a313f37c..d120421b416d9 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.pt-BR.xlf
@@ -142,6 +142,11 @@
Preferir a criação de objeto implícito quando o tipo for aparente
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Preferir a correspondência de padrões
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf
index 8337be2b11d50..9bb3a8631fa78 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.ru.xlf
@@ -142,6 +142,11 @@
Предпочитать неявное создание объекта, когда тип очевиден.
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Предпочитать соответствие шаблону
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf
index 9400db37331ff..77bb0bf7bb6de 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.tr.xlf
@@ -142,6 +142,11 @@
Tür görünür olduğunda örtük nesne oluşturmayı tercih et
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
Desen eşleştirmeyi tercih et
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf
index 6e6d46a78e19c..b54dba08ed3f1 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hans.xlf
@@ -142,6 +142,11 @@
类型明显时首选隐式对象创建
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
首选模式匹配
diff --git a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf
index 97b2e8f4ade82..e4f89e27cb877 100644
--- a/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf
+++ b/src/VisualStudio/CSharp/Impl/xlf/CSharpVSResources.zh-Hant.xlf
@@ -142,6 +142,11 @@
當類型為實際型態時,建議建立隱含物件
+
+ Prefer implicitly typed lambda expression
+ Prefer implicitly typed lambda expression
+
+
Prefer pattern matching
建議使用模式比對
diff --git a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs
index a830da016df2c..b838cbd7a7fbf 100644
--- a/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs
+++ b/src/VisualStudio/Core/Def/Options/VisualStudioOptionStorage.cs
@@ -206,6 +206,7 @@ public bool TryFetch(LocalUserRegistryOptionPersister persister, OptionKey2 opti
{"csharp_style_pattern_matching_over_as_with_null_check", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferPatternMatchingOverAsWithNullCheck")},
{"csharp_style_pattern_matching_over_is_with_cast_check", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferPatternMatchingOverIsWithCastCheck")},
{"csharp_style_prefer_extended_property_pattern", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferExtendedPropertyPattern")},
+ {"csharp_style_prefer_implicitly_typed_lambda_expression", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferImplicitlyTypedLambdaExpression")},
{"csharp_style_prefer_index_operator", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferIndexOperator")},
{"csharp_style_prefer_local_over_anonymous_function", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferLocalOverAnonymousFunction")},
{"csharp_style_prefer_method_group_conversion", new RoamingProfileStorage("TextEditor.CSharp.Specific.PreferMethodGroupConversion")},
diff --git a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb
index d04445a96d69a..9fa99df3d2858 100644
--- a/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb
+++ b/src/VisualStudio/Core/Test/Options/CSharpEditorConfigGeneratorTests.vb
@@ -153,6 +153,7 @@ csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
+csharp_style_prefer_implicitly_typed_lambda_expression = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true
@@ -413,6 +414,7 @@ csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
+csharp_style_prefer_implicitly_typed_lambda_expression = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_null_check_over_type_check = true
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs
index 596029387e652..c484d9584c3a2 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/CodeStyle/CSharpCodeStyleOptions.cs
@@ -149,6 +149,11 @@ private static Option2> CreatePreferE
"csharp_prefer_simple_default_expression",
CSharpSimplifierOptions.Default.PreferSimpleDefaultExpression);
+ public static readonly Option2> PreferImplicitlyTypedLambdaExpression = CreateOption(
+ CodeStyleOptionGroups.ExpressionLevelPreferences,
+ "csharp_style_prefer_implicitly_typed_lambda_expression",
+ CSharpSimplifierOptions.Default.PreferImplicitlyTypedLambdaExpression);
+
private static readonly ImmutableArray s_preferredModifierOrderDefault =
[
SyntaxKind.PublicKeyword,
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs
index bd616fa208148..4eb4949de556d 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/CSharp/Simplification/CSharpSimplifierOptions.cs
@@ -24,6 +24,7 @@ internal sealed record class CSharpSimplifierOptions : SimplifierOptions, IEquat
[DataMember] public CodeStyleOption2 VarWhenTypeIsApparent { get; init; } = CodeStyleOption2.FalseWithSilentEnforcement;
[DataMember] public CodeStyleOption2 VarElsewhere { get; init; } = CodeStyleOption2.FalseWithSilentEnforcement;
[DataMember] public CodeStyleOption2 PreferSimpleDefaultExpression { get; init; } = CodeStyleOption2.TrueWithSuggestionEnforcement;
+ [DataMember] public CodeStyleOption2 PreferImplicitlyTypedLambdaExpression { get; init; } = CodeStyleOption2.TrueWithSuggestionEnforcement;
[DataMember] public CodeStyleOption2 PreferParameterNullChecking { get; init; } = CodeStyleOption2.TrueWithSuggestionEnforcement;
[DataMember] public CodeStyleOption2 AllowEmbeddedStatementsOnSameLine { get; init; } = CodeStyleOption2.TrueWithSilentEnforcement;
[DataMember] public CodeStyleOption2 PreferBraces { get; init; } = s_defaultPreferBraces;
@@ -41,6 +42,7 @@ public CSharpSimplifierOptions(IOptionsReader options)
VarWhenTypeIsApparent = options.GetOption(CSharpCodeStyleOptions.VarWhenTypeIsApparent);
VarElsewhere = options.GetOption(CSharpCodeStyleOptions.VarElsewhere);
PreferSimpleDefaultExpression = options.GetOption(CSharpCodeStyleOptions.PreferSimpleDefaultExpression);
+ PreferImplicitlyTypedLambdaExpression = options.GetOption(CSharpCodeStyleOptions.PreferImplicitlyTypedLambdaExpression);
AllowEmbeddedStatementsOnSameLine = options.GetOption(CSharpCodeStyleOptions.AllowEmbeddedStatementsOnSameLine);
PreferBraces = options.GetOption(CSharpCodeStyleOptions.PreferBraces);
PreferThrowExpression = options.GetOption(CSharpCodeStyleOptions.PreferThrowExpression);
diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SignatureComparer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SignatureComparer.cs
index 67c9b538c5f15..1e800736f56c0 100644
--- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SignatureComparer.cs
+++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SignatureComparer.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
namespace Microsoft.CodeAnalysis.Shared.Utilities;
@@ -103,34 +104,28 @@ private static bool IdentifiersMatch(string identifier1, string identifier2, boo
}
public bool HaveSameSignature(
- IList parameters1,
- IList parameters2)
+ ImmutableArray parameters1,
+ ImmutableArray parameters2)
{
- if (parameters1.Count != parameters2.Count)
- {
+ if (parameters1.Length != parameters2.Length)
return false;
- }
return parameters1.SequenceEqual(parameters2, this.ParameterEquivalenceComparer);
}
public bool HaveSameSignature(
- IList parameters1,
- IList parameters2,
+ ImmutableArray parameters1,
+ ImmutableArray parameters2,
bool compareParameterName,
bool isCaseSensitive)
{
- if (parameters1.Count != parameters2.Count)
- {
+ if (parameters1.Length != parameters2.Length)
return false;
- }
- for (var i = 0; i < parameters1.Count; ++i)
+ for (var i = 0; i < parameters1.Length; ++i)
{
if (!_symbolEquivalenceComparer.ParameterEquivalenceComparer.Equals(parameters1[i], parameters2[i], compareParameterName, isCaseSensitive))
- {
return false;
- }
}
return true;