Тема неоднозначних виключень (Ambiguous Match Exception) та їх обробка з точки зору продуктивності

pic

Команда вже виправляла код, але виникла помилка "Ambiguous Match Exception", тому я вирішив записати це в блозі.

Оригінальна стаття: เรื่องของ Ambiguous Match Exception และการจัดการในมุม Performance — Naiwaen@DebuggingSoft

Що таке Ambiguous Match Exception?

Коли ми використовуємо Reflection в dotnet, іноді результат може містити два однакові елементи. Наприклад, у наведеному коді, якщо використовувати Reflection, ми побачимо дві властивості MyProperty — одну типу int і одну типу String.

public class BaseClass  
{  
 public int MyProperty { get; set; }  
 public int a { get; set; }  
}  

public class DerivedClass : BaseClass  
{  
 public new string MyProperty { get; set; }  
 public int b { get; set; }  
}

Обговорення варіантів виправлення

Тепер потрібно вирішити, як виправити цю проблему:

  • Просто взяти перший результат
  • Використати блок Try-Catch, щоб при виникненні AmbiguousMatchException спробувати ще раз, використовуючи:
    • BindingFlags.Instance
    • BindingFlags.Public
    • BindingFlags.DeclaredOnly

Ось два підходи, але виникає питання щодо продуктивності, тому я вирішив написати тестовий код для порівняння часу.

using System;  
using System.Diagnostics;  
using System.Linq;  
using System.Reflection;  

public class BaseClass  
{  
 public int MyProperty { get; set; }  
 public int a { get; set; }  
}  

public class DerivedClass : BaseClass  
{  
 public new string MyProperty { get; set; }  
 public int b { get; set; }  
}  

class Program  
{  
 static void Main()  
 {  
 Type type = typeof(DerivedClass);  
 string path = "MyProperty";  
 int iterations = 100000;  

 // Порівняння першого фрагменту коду  
 Stopwatch stopwatch1 = Stopwatch.StartNew();  
 for (int i = 0; i < iterations; i++)  
 {  
 PropertyInfo[] infos = type.GetProperties();  
 PropertyInfo info = infos.FirstOrDefault(p => p.Name.Equals(path, StringComparison.OrdinalIgnoreCase));  
 }  
 stopwatch1.Stop();  
 Console.WriteLine($"Час першого фрагменту коду: {stopwatch1.ElapsedMilliseconds} ms");  

 // Порівняння другого фрагменту коду  
 Stopwatch stopwatch2 = Stopwatch.StartNew();  
 for (int i = 0; i < iterations; i++)  
 {  
 PropertyInfo info = null;  
 try  
 {  
 info = type.GetProperty(path);  
 }  
 catch (AmbiguousMatchException)  
 {  
 info = type.GetProperty(path, BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);  
 }  
 }  
 stopwatch2.Stop();  
 Console.WriteLine($"Час другого фрагменту коду: {stopwatch2.ElapsedMilliseconds} ms");  
 }  
}

Щоб спробувати запустити код, можете використати https://dotnetfiddle.net/omhnmQ.

Результати виглядають так:

Час першого фрагменту коду: 52 ms  
Час другого фрагменту коду: 1558 ms

Як видно, перший код, без обробки виключень, займає менше часу, ніж другий, де часто відбувається перехоплення виключення. Якщо таких випадків буде багато, це може стати великою проблемою для продуктивності.

Щоб уникнути таких ситуацій, необхідно встановити стандарт кодування, що дозволить уникнути проблем і поліпшить загальну продуктивність додатку. ^__^

Підтримати & Пожертвувати: https://www.buymeacoffee.com/pingkunga

Перекладено з: เรื่องของ ambiguous match exception และการจัดการในมุม Performance

Leave a Reply

Your email address will not be published. Required fields are marked *