Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce CA1854 performance analyzer #22100

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ public IEnumerable<Instruction> ConvertFromString(string value, ILContext contex
//Device.GetNamedSize(namedSize, targetObject.GetType())
yield return Instruction.Create(OpCodes.Ldc_I4, (int)namedSize);
var parent = node.Parent as IElementNode;
if (parent != null && context.Variables.ContainsKey(parent))
if (parent != null && context.Variables.TryGetValue(parent, out VariableDefinition parentValue))
{
yield return Instruction.Create(OpCodes.Ldloc, context.Variables[parent]);
yield return Instruction.Create(OpCodes.Ldloc, parentValue);
yield return Instruction.Create(OpCodes.Callvirt, module.ImportMethodReference(
context.Cache,
module.TypeSystem.Object,
Expand Down
15 changes: 8 additions & 7 deletions src/Controls/src/Build.Tasks/CreateObjectVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@ public void Visit(ElementNode node, INode parentNode)
MethodDefinition factoryMethodInfo = null;
MethodDefinition parameterizedCtorInfo = null;
MethodDefinition ctorInfo = null;

if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod))

INode factoryMethodNode = null;
if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.TryGetValue(XmlName.xFactoryMethod, out factoryMethodNode))
{
factoryCtorInfo = typedef.AllMethods(Context.Cache).FirstOrDefault(md => md.methodDef.IsConstructor &&
!md.methodDef.IsStatic &&
Expand All @@ -107,9 +108,9 @@ public void Visit(ElementNode node, INode parentNode)
if (!typedef.IsValueType) //for ctor'ing typedefs, we first have to ldloca before the params
Context.IL.Append(PushCtorXArguments(factoryCtorInfo.ResolveGenericParameters(typeref, Module), node));
}
else if (node.Properties.ContainsKey(XmlName.xFactoryMethod))
else if (factoryMethodNode != null)
{
var factoryMethod = (string)(node.Properties[XmlName.xFactoryMethod] as ValueNode).Value;
var factoryMethod = (string)(factoryMethodNode as ValueNode).Value;
factoryMethodInfo = typedef.AllMethods(Context.Cache).FirstOrDefault(md => !md.methodDef.IsConstructor &&
md.methodDef.Name == factoryMethod &&
md.methodDef.IsStatic &&
Expand Down Expand Up @@ -317,14 +318,14 @@ IEnumerable<Instruction> PushCtorArguments(MethodReference ctorinfo, ElementNode

IEnumerable<Instruction> PushCtorXArguments(MethodReference factoryCtorInfo, ElementNode enode)
{
if (!enode.Properties.ContainsKey(XmlName.xArguments))
if (!enode.Properties.TryGetValue(XmlName.xArguments, out INode value))
yield break;

var arguments = new List<INode>();
var node = enode.Properties[XmlName.xArguments] as ElementNode;
var node = value as ElementNode;
if (node != null)
arguments.Add(node);
var list = enode.Properties[XmlName.xArguments] as ListNode;
var list = value as ListNode;
if (list != null)
{
foreach (var n in list.CollectionItems)
Expand Down
6 changes: 3 additions & 3 deletions src/Controls/src/Build.Tasks/MethodDefinitionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ static class MethodDefinitionExtensions
{
public static bool MatchXArguments(this MethodDefinition methodDef, ElementNode enode, TypeReference declaringTypeRef, ModuleDefinition module, ILContext context)
{
if (!enode.Properties.ContainsKey(XmlName.xArguments))
if (!enode.Properties.TryGetValue(XmlName.xArguments, out INode value))
return !methodDef.HasParameters;

var arguments = new List<INode>();
var node = enode.Properties[XmlName.xArguments] as ElementNode;
var node = value as ElementNode;
if (node != null)
arguments.Add(node);

var list = enode.Properties[XmlName.xArguments] as ListNode;
var list = value as ListNode;
if (list != null)
foreach (var n in list.CollectionItems)
arguments.Add(n);
Expand Down
8 changes: 4 additions & 4 deletions src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,9 +1499,9 @@ static bool CanAddToResourceDictionary(VariableDefinition parent, TypeReference
&& !collectionType.InheritsFromOrImplements(context.Cache, context.Module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"))))
return false;

if (node.Properties.ContainsKey(XmlName.xKey))
if (node.Properties.TryGetValue(XmlName.xKey, out INode nodePropertyValue))
{
var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null);
var valueNode = nodePropertyValue as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null);
var key = (valueNode).Value as string;
var names = context.Cache.GetResourceNamesInUse(parent);
if (names.Contains(key))
Expand Down Expand Up @@ -1552,10 +1552,10 @@ static IEnumerable<Instruction> AddToResourceDictionary(VariableDefinition paren
{
var module = context.Body.Method.Module;

if (node.Properties.ContainsKey(XmlName.xKey))
if (node.Properties.TryGetValue(XmlName.xKey, out INode nodePropertyValue))
{
var names = context.Cache.GetResourceNamesInUse(parent);
var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null);
var valueNode = nodePropertyValue as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null);
var key = (valueNode).Value as string;
names.Add(key);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,9 @@ protected virtual void OnShellSectionPropertyChanged(object sender, PropertyChan
_currentContent = newContent;
_currentIndex = newIndex;

if (!_renderers.ContainsKey(newContent))
if (!_renderers.TryGetValue(newContent, out var currentRenderer))
return;

var currentRenderer = _renderers[newContent];
_isAnimatingOut = oldRenderer;
_pageAnimation?.StopAnimation(true);
_pageAnimation = null;
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core/Internals/NameScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ void INameScope.UnregisterName(string name)
if (name == "")
throw new ArgumentException("name was provided as empty string.", nameof(name));

if (!_names.ContainsKey(name))
if (!_names.TryGetValue(name, out var nameValue))
throw new ArgumentException("name provided had not been registered.", nameof(name));

_values.Remove(_names[name]);
_values.Remove(nameValue);
_names.Remove(name);
}
}
Expand Down
20 changes: 10 additions & 10 deletions src/Controls/src/Core/MessagingCenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,21 +202,21 @@ void InnerSend(string message, Type senderType, Type argType, object sender, obj
if (message == null)
throw new ArgumentNullException(nameof(message));
var key = new Sender(message, senderType, argType);
if (!_subscriptions.ContainsKey(key))
if (!_subscriptions.TryGetValue(key, out List<Subscription> subscriptions))
return;
List<Subscription> subcriptions = _subscriptions[key];
if (subcriptions == null || !subcriptions.Any())

if (subscriptions == null || !subscriptions.Any())
return; // should not be reachable

// ok so this code looks a bit funky but here is the gist of the problem. It is possible that in the course
// of executing the callbacks for this message someone will subscribe/unsubscribe from the same message in
// the callback. This would invalidate the enumerator. To work around this we make a copy. However if you unsubscribe
// from a message you can fairly reasonably expect that you will therefor not receive a call. To fix this we then
// check that the item we are about to send the message to actually exists in the live list.
List<Subscription> subscriptionsCopy = subcriptions.ToList();
List<Subscription> subscriptionsCopy = subscriptions.ToList();
foreach (Subscription subscription in subscriptionsCopy)
{
if (subscription.Subscriber.Target != null && subcriptions.Contains(subscription))
if (subscription.Subscriber.Target != null && subscriptions.Contains(subscription))
{
subscription.InvokeCallback(sender, args);
}
Expand All @@ -229,9 +229,9 @@ void InnerSubscribe(object subscriber, string message, Type senderType, Type arg
throw new ArgumentNullException(nameof(message));
var key = new Sender(message, senderType, argType);
var value = new Subscription(subscriber, target, methodInfo, filter);
if (_subscriptions.ContainsKey(key))
if (_subscriptions.TryGetValue(key, out List<Subscription> subscriptions))
{
_subscriptions[key].Add(value);
subscriptions.Add(value);
}
else
{
Expand All @@ -248,10 +248,10 @@ void InnerUnsubscribe(string message, Type senderType, Type argType, object subs
throw new ArgumentNullException(nameof(message));

var key = new Sender(message, senderType, argType);
if (!_subscriptions.ContainsKey(key))
if (!_subscriptions.TryGetValue(key, out List<Subscription> subscriptions))
return;
_subscriptions[key].RemoveAll(sub => sub.CanBeRemoved() || sub.Subscriber.Target == subscriber);
if (!_subscriptions[key].Any())
subscriptions.RemoveAll(sub => sub.CanBeRemoved() || sub.Subscriber.Target == subscriber);
if (!subscriptions.Any())
_subscriptions.Remove(key);
}

Expand Down
8 changes: 4 additions & 4 deletions src/Controls/src/Core/ResourceDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ public bool ContainsKey(string key)
{
get
{
if (_innerDictionary.ContainsKey(index))
return _innerDictionary[index];
if (_mergedInstance != null && _mergedInstance.ContainsKey(index))
return _mergedInstance[index];
if (_innerDictionary.TryGetValue(index, out var innerValue))
return innerValue;
if (_mergedInstance != null && _mergedInstance.TryGetValue(index, out var mergedValue))
return mergedValue;
if (_mergedDictionaries != null)
{
var dictionaries = (ObservableCollection<ResourceDictionary>)MergedDictionaries;
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core/ResourcesExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ static class ResourcesExtensions
{
resources = resources ?? new Dictionary<string, object>(8, StringComparer.Ordinal);
foreach (KeyValuePair<string, object> res in app.SystemResources)
if (!resources.ContainsKey(res.Key))
if (!resources.TryGetValue(res.Key, out var resourceValue))
resources.Add(res.Key, res.Value);
else if (res.Key.StartsWith(Style.StyleClassPrefix, StringComparison.Ordinal))
{
var mergedClassStyles = new List<Style>(resources[res.Key] as List<Style>);
var mergedClassStyles = new List<Style>(resourceValue as List<Style>);
mergedClassStyles.AddRange(res.Value as List<Style>);
resources[res.Key] = mergedClassStyles;
}
Expand Down
10 changes: 5 additions & 5 deletions src/Controls/src/Xaml/ApplyPropertiesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ public void Visit(ElementNode node, INode parentNode)

string xKey = null;
if (xpe == null
&& node.Properties.ContainsKey(XmlName.xKey))
&& node.Properties.TryGetValue(XmlName.xKey, out INode nodePropertyValue))
{
if ((node.Properties[XmlName.xKey] is ValueNode valueNode))
if (nodePropertyValue is ValueNode valueNode)
xKey = valueNode.Value as string;
if (xKey == null)
xpe = new XamlParseException("x:Key expects a string literal.", node as IXmlLineInfo);
Expand Down Expand Up @@ -192,9 +192,9 @@ public void Visit(ElementNode node, INode parentNode)
return;
Exception xpe = null;
string xKey = null;
if (xpe == null && node.Properties.ContainsKey(XmlName.xKey))
if (xpe == null && node.Properties.TryGetValue(XmlName.xKey, out INode nodePropertyValue))
{
if ((node.Properties[XmlName.xKey] is ValueNode valueNode))
if (nodePropertyValue is ValueNode valueNode)
xKey = valueNode.Value as string;
if (xKey == null)
xpe = new XamlParseException("x:Key expects a string literal.", node as IXmlLineInfo);
Expand Down Expand Up @@ -357,7 +357,7 @@ static object GetTargetProperty(object xamlelement, XmlName propertyName, object
public static void SetPropertyValue(object xamlelement, XmlName propertyName, object value, object rootElement, INode node, HydrationContext context, IXmlLineInfo lineInfo)
{
var serviceProvider = new XamlServiceProvider(node, context);
var xKey = node is IElementNode eNode && eNode.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)eNode.Properties[XmlName.xKey]).Value as string : null;
var xKey = node is IElementNode eNode && eNode.Properties.TryGetValue(XmlName.xKey, out INode nodePropertyValue) ? ((ValueNode)nodePropertyValue).Value as string : null;

if (TrySetPropertyValue(xamlelement, propertyName, xKey, value, rootElement, lineInfo, serviceProvider, out var xpe))
return;
Expand Down
8 changes: 4 additions & 4 deletions src/Controls/src/Xaml/CreateValuesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,13 @@ public object CreateFromFactory(Type nodeType, IElementNode node)
{
object[] arguments = CreateArgumentsArray(node);

if (!node.Properties.ContainsKey(XmlName.xFactoryMethod))
if (!node.Properties.TryGetValue(XmlName.xFactoryMethod, out INode nodePropertyValue))
{
//non-default ctor
return Activator.CreateInstance(nodeType, arguments);
}

var factoryMethod = ((string)((ValueNode)node.Properties[XmlName.xFactoryMethod]).Value);
var factoryMethod = (string)((ValueNode)nodePropertyValue).Value;
Type[] types = arguments == null ? Array.Empty<Type>() : arguments.Select(a => a.GetType()).ToArray();

bool isMatch(MethodInfo m)
Expand Down Expand Up @@ -266,9 +266,9 @@ bool isMatch(MethodInfo m)

public object[] CreateArgumentsArray(IElementNode enode)
{
if (!enode.Properties.ContainsKey(XmlName.xArguments))
if (!enode.Properties.TryGetValue(XmlName.xArguments, out INode node))
return null;
var node = enode.Properties[XmlName.xArguments];

if (node is ElementNode elementNode)
{
var array = new object[1];
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Xaml/SimplifyTypeExtensionVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ static bool IsTypeExtension(ElementNode node, out ValueNode typeNameValueNode)

if (node.XmlType.Name == nameof(TypeExtension)
&& node.XmlType.NamespaceUri == XamlParser.X2009Uri
&& node.Properties.ContainsKey(typeNameXmlName)
&& node.Properties[typeNameXmlName] is ValueNode valueNode
&& node.Properties.TryGetValue(typeNameXmlName, out INode nodePropertyValue)
&& nodePropertyValue is ValueNode valueNode
&& valueNode.Value is string)
{
typeNameValueNode = valueNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ public void Register(Type type, Func<object, object> factory)

public object Resolve(Type type, params object[] args)
{
if (_services.ContainsKey(type))
if (_services.TryGetValue(type, out var service))
{
return _services[type];
return service;
}

if (_factories.ContainsKey(type))
if (_factories.TryGetValue(type, out Func<object, object> factory))
{
return _factories[type].Invoke(args[0]);
return factory.Invoke(args[0]);
}

return null;
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dotnet_diagnostic.CA1834.severity = error
dotnet_diagnostic.CA1845.severity = error
dotnet_diagnostic.CA1846.severity = error
dotnet_diagnostic.CA1847.severity = error
dotnet_diagnostic.CA1854.severity = error
dotnet_diagnostic.CA1859.severity = error
dotnet_diagnostic.CA1860.severity = error
dotnet_diagnostic.CA1864.severity = error
Expand Down
7 changes: 4 additions & 3 deletions src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decima
cache = new Dictionary<char, LocalizedDigitsKeyListener>(1);
}

if (!cache.ContainsKey(decimalSeparator))
if (!cache.TryGetValue(decimalSeparator, out LocalizedDigitsKeyListener? listener))
{
cache.Add(decimalSeparator, new LocalizedDigitsKeyListener(inputTypes, decimalSeparator));
listener = new LocalizedDigitsKeyListener(inputTypes, decimalSeparator);
cache.Add(decimalSeparator, listener);
}

return cache[decimalSeparator];
return listener;
}

protected LocalizedDigitsKeyListener(InputTypes inputTypes, char decimalSeparator)
Expand Down
6 changes: 3 additions & 3 deletions src/Core/src/Platform/Tizen/StackNavigationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,16 @@ void NavigationFinished(IReadOnlyList<IView> stack)

NaviPage GetNavigationItem(IView page)
{
if (_pageMap.ContainsKey(page))
if (_pageMap.TryGetValue(page, out var naviPage))
{
return _pageMap[page];
return naviPage;
}

var content = page.ToPlatform(MauiContext!);
content.WidthSpecification = LayoutParamPolicies.MatchParent;
content.HeightSpecification = LayoutParamPolicies.MatchParent;

var naviPage = new NaviPage
naviPage = new NaviPage
{
Content = content,
WidthSpecification = LayoutParamPolicies.MatchParent,
Expand Down
15 changes: 7 additions & 8 deletions src/Core/src/Platform/Tizen/WindowExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ public static void SetContent(this Window platformWindow, View content)
content.HeightResizePolicy = ResizePolicyType.FillToParent;
content.WidthResizePolicy = ResizePolicyType.FillToParent;

if (s_modalStacks.ContainsKey(platformWindow))
if (s_modalStacks.TryGetValue(platformWindow, out var modalStack))
{
var modalStack = s_modalStacks[platformWindow];
modalStack.Clear();
modalStack.Push(content, true);
}
Expand Down Expand Up @@ -62,8 +61,8 @@ public static void Initialize(this Window platformWindow)

public static NavigationStack? GetModalStack(this Window platformWindow)
{
if (s_modalStacks.ContainsKey(platformWindow))
return s_modalStacks[platformWindow];
if (s_modalStacks.TryGetValue(platformWindow, out var modalStack))
return modalStack;
return null;
}

Expand Down Expand Up @@ -103,14 +102,14 @@ static void OnRotate(Window platformWindow)

static void OnBackButtonPressed(Window platformWindow)
{
if (s_windowBackButtonPressedHandler.ContainsKey(platformWindow))
if (s_windowBackButtonPressedHandler.TryGetValue(platformWindow, out var pressedHandler))
{
if (s_windowBackButtonPressedHandler[platformWindow].Invoke())
if (pressedHandler.Invoke())
return;
}

if (s_windowCloseRequestHandler.ContainsKey(platformWindow))
s_windowCloseRequestHandler[platformWindow].Invoke();
if (s_windowCloseRequestHandler.TryGetValue(platformWindow, out var requestHandler))
requestHandler.Invoke();
}

internal static void UpdateX(this Window platformWindow, IWindow window) =>
Expand Down
4 changes: 2 additions & 2 deletions src/Essentials/src/Permissions/Permissions.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,10 @@ internal static void OnRequestPermissionsResult(int requestCode, string[] permis
{
lock (locker)
{
if (requests.ContainsKey(requestCode))
if (requests.TryGetValue(requestCode, out var requestResult))
{
var result = new PermissionResult(permissions, grantResults);
requests[requestCode].TrySetResult(result);
requestResult.TrySetResult(result);
requests.Remove(requestCode);
}
}
Expand Down