#c# #null #argumentnullexception
Вопрос:
вот небольшая часть кода, если у кого-то есть идеи, не стесняйтесь подбадривать меня!
public decimal getBook(string pair, decimal amount, string type, string operation, bool division = true) { try { //book is null BinanceOrderBook book = null; foreach (var item in Program.array) if ((item as Program.ClassDetailOrder).symbol == pair.ToLower()) { book = (item as Program.ClassDetailOrder).book; break; } // 'lst' is also null nut lst depends on book to not be null. lst is a list but created on the results of the ifs below (ask and bid are api calls ) Listlt;BinanceOrderBookEntrygt; lst = null; if (type == "asks") lst = book.Asks; if (type == "bids") lst = book.Bids; decimal[] arrayValue = new decimal[2]; arrayValue[0] = arrayValue[1] = 0; decimal orderPrice = 0; decimal orderAmount = 0; decimal totalCost = 0; decimal totalAmount = 0; decimal remaining = amount; decimal cost = 0; foreach (var item in lst) { orderPrice = item.Price; orderAmount = item.Quantity; cost = orderPrice * orderAmount; if (cost lt; remaining) { remaining -= cost; totalCost = cost; totalAmount = orderAmount; } else { //finished remaining -= amount; totalCost = amount * orderPrice; totalAmount = amount; if (division) { arrayValue[0] = Math.Round(amount / (totalCost / totalAmount), 8); arrayValue[1] = Math.Round(amount / orderPrice, 8); } else { arrayValue[0] = Math.Round((totalCost / totalAmount) * amount, 8); arrayValue[1] = Math.Round(orderPrice * amount, 8); } return arrayValue[0]; } } } catch (Exception ex) { } }
Ответ №1:
Если я правильно понимаю архитектуру вашего приложения, добавление нескольких нулевых проверок может решить вашу проблему.
Ваши модели:
public class ClassDetailOrder { public BinanceOrderBook Book { get; set; } public string Symbol { get; set; } } public class BinanceOrderBook { public Listlt;BinanceOrderBookEntrygt; Asks { get; set; } public Listlt;BinanceOrderBookEntrygt; Bids { get; set; } } public class BinanceOrderBookEntry { public decimal Price { get; set; } public decimal Quantity { get; set; } }
Ваш массив ClassDetailOrder
с некоторыми значениями (пример):
private readonly ClassDetailOrder[] array = new ClassDetailOrder[] { // Item 0 null, // Item 1 new ClassDetailOrder { Book = new BinanceOrderBook { Asks = new Listlt;BinanceOrderBookEntrygt;() { new BinanceOrderBookEntry { Price = 50, Quantity = 5 } } }, Symbol = "book1" }, // Item 2 new ClassDetailOrder { Book = new BinanceOrderBook { Bids = new Listlt;BinanceOrderBookEntrygt;() { new BinanceOrderBookEntry { Price = 100, Quantity = 10 } } }, Symbol = "book2" }, };
Вызов GetBook
метода с различными параметрами:
private void GetSomeBooks() { GetBook("Book0", 1, "asks", ""); GetBook(null, 2, "bids", ""); GetBook("Book2", 3, "asks", ""); GetBook("Book1", 4, null, ""); }
И ваш GetBook
метод (с некоторыми моими дополнениями, изменениями и комментариями):
public decimal GetBook(string pair, decimal amount, string type, string operation, bool division = true) { // Default value var result = -1.0M; try { if (array is null) { // Handle in some way that "Array of ClassDetailOrders was null." return result; } if (string.IsNullOrEmpty(pair)) { // Handle in some way that "Pair value must be specified." return result; } // Getting first Book from not-null(!) ClassDetailOrder, // which Symbol matches to provided "pair" value var book = array.FirstOrDefault(item =gt; item?.Symbol == pair.ToLower())?.Book; // Book will be null if: // - all ClassDetailOrders in array was null // - no ClassDetailOrder with some Symbol that match to pair.ToLower() was found // - Book property of founded ClassDetailOrder was null by itself // Checking Book is null or not and go out from method if null if (book is null) { // Handle in some way that "Specified Book wasn't found." return result; } // If Book wasn't null, initializing List var lst = (Listlt;BinanceOrderBookEntrygt;)null; // Provided "type" value also may be null or empty if (string.IsNullOrEmpty(type)) { // Handle in some way that "Book Type must be specified." return result; } switch (type) { case "asks": lst = book.Asks; break; case "bids": lst = book.Bids; break; } // Same null-check as for Book above, but for List now if (lst is null) { // Handle in some way that "Book items of provided Type was null."; return result; } decimal[] arrayValue = new decimal[2] { 0M, 0M }; decimal orderPrice = 0, orderAmount = 0, totalCost = 0, totalAmount = 0, cost = 0; decimal remaining = amount; foreach (var item in lst) { // Same null-check as for Book and List above if (item is null) { // Handle in some way that item was null, e.g.: continue; // or return result; } orderPrice = item.Price; orderAmount = item.Quantity; cost = orderPrice * orderAmount; remaining = cost lt; remaining ? remaining - cost : remaining - amount; totalCost = cost lt; remaining ? totalCost cost : amount * orderPrice; totalAmount = cost lt; remaining ? totalAmount orderAmount : totalAmount amount; // Reversed if because of ternary replacements if (cost gt;= remaining) { arrayValue[0] = division ? Math.Round(amount / (totalCost / totalAmount), 8) : Math.Round(totalCost / totalAmount * amount, 8); arrayValue[1] = division ? Math.Round(amount / orderPrice, 8) : Math.Round(orderPrice * amount, 8); result = arrayValue[0]; } } } catch (Exception ex) { MessageBox.Show(ex.Message); } return result; }
Основная идея, которую вы должны понять, состоит в том, чтобы проверять каждый объект, допускающий обнуление, на возможное нулевое значение, где это возможно. В этом примере у нас, возможно, может быть 8 объектов, которые могут быть null
и могут вызвать NullReferenceException
. И ты сможешь справиться со всеми ними:
- Для
array
офClassDetailOrder
(чтобы иметь возможность искатьClassDetailOrder
в нем предметы); - Для указанного
pair
значения (чтобы избежать исключения null при использовании нижнего регистраToLower()
); - Для каждого
ClassDetailOrder
(чтобы избежать нулевых исключений при поискеBook
); - Для
ClassDetailOrder
результата at (если методом никто не был найденFirstOrDefault
); - Для
Book
(чтобы быть уверенными, что мы можем получить доступ к немуAsks
/Bids
спискам); - За предоставленную
type
стоимость (чтобы быть уверенным, что вы можете принять надлежащиеList
(запросы или ставки или любые другие, которые у вас будут)); - Для
List
(чтобы быть уверенным, чтоList
по крайней мере пусто, но не равно нулю); - Для
BinanceOrderBookEntry
элемента вforeach
циклеList
(чтобы убедиться, что мы можем получить доступ к егоPrice
свойствам иQuantity
свойствам).
Вы можете обрабатывать проверки на нуль так, как вы хотите, или возвращать значение, которое вы хотите, или изменять if
значение s на is not null
( != null
).
You can tests different values to try cover all null-checks and test them.