AskalotLearnalot Ответов: 2

Как передать элементы массива из метода в другой метод


Я сделал метод который отлично работает он получает значения штрих кодов вот этот метод:
public Array ReadBarcodeFromFile(string _Filepath, string strTopBarCode, string strMiddleBarCode, string strBottomBarCode)
        {
            String[] barcodes = BarcodeScanner.Scan(_Filepath, BarcodeType.Code39);
            if (barcodes.Length != 0)
            {
                strTopBarCode = barcodes[0];
                strMiddleBarCode = barcodes[1];
                strBottomBarCode = barcodes[2];
                return barcodes;
            }

            return null; 
        }

когда я позвоню. значения параметров изменяются от нуля до правильных значений. Кроме того, прежде чем я достигну конца метода, Если я проверю значения параметров в другом методе, которому я хочу передать значения, я все равно получу правильное значение.
Однако, когда я достигаю конца метода, эти значения изменяются на null.
Вот мой другой метод:
public ActionResult Index(string strTopBarCode, string strMiddleBarCode, string strBottomBarCode)
        {
            string barcodeTopParent = "something1";
                    string barcodeMiddleParent = "something2";
                    string barcodeBottomParent = "something3";
                      
                        helper.ReadBarcodeFromFile(file.FullName, strTopBarCode, strMiddleBarCode, strBottomBarCode);
                          //strTopBarCode strMiddleBarCode strBottomBarCode always become null even though the method doesn't pass null
                        if (strTopBarCode == barcodeTopParent || strMiddleBarCode == barcodeMiddleParent || strBottomBarCode == barcodeBottomParent)
                        {
                           
                          //do something
                        }

Я думаю, что это проблема возврата, и это что-то простое из-за отсутствия опыта. Заранее спасибо.

Что я уже пробовал:

приведенный выше код-это то, что я пробовал. Я также попробовал метод типа string, который возвращает только один элемент и добавляет его к значению в результате действия, которое работает:
string oneBarcode = helper.ReadBarcodeFromFile(file.FullName)

Метод:
public Array ReadBarcodeFromFile(string _Filepath)
        {
            String[] barcodes = BarcodeScanner.Scan(_Filepath, BarcodeType.Code39);
            if (barcodes.Length != 0)
            {
                return barcodes[0];
               }             
            return null; 
        }

2 Ответов

Рейтинг:
7

Richard Deeming

По умолчанию параметры передаются по значению. Это означает, что любые изменения, внесенные в значение параметров внутри метода, не будут видны вызывающему методу.

Передача Параметров - Руководство По Программированию На C# | Microsoft Docs[^]
Передача параметров в C#[^]

Если вы хотите, чтобы изменения были видны вызывающему методу, то вам нужно передать параметры по ссылке. Вы делаете это, используя либо ref или out модификаторы.

ключевое слово ref - ссылка на C# | Microsoft Docs[^]
модификатор параметров out - Справочник по C# | Microsoft Docs[^]

Например:

public ActionResult Index()
{
    const string barcodeTopParent = "DT-COMPSTART";
    const string barcodeMiddleParent = "DB-TEST";
    const string barcodeBottomParent = "SP-SLD";
    
    string strTopBarCode, strMiddleBarCode, strBottomBarCode;
    helper.ReadBarcodeFromFile(file.FullName, out strTopBarCode, out strMiddleBarCode, out strBottomBarCode);
    if (strTopBarCode == barcodeTopParent || strMiddleBarCode == barcodeMiddleParent || strBottomBarCode == barcodeBottomParent)
    {
        ...
    }
}

public void ReadBarcodeFromFile(string _Filepath, out string strTopBarCode, out string strMiddleBarCode, out string strBottomBarCode)
{
    string[] barcodes = BarcodeScanner.Scan(_Filepath, BarcodeType.Code39);
    if (barcodes.Length != 0)
    {
        strTopBarCode = barcodes[0];
        strMiddleBarCode = barcodes[1];
        strBottomBarCode = barcodes[2];
    }
    else
    {
        strTopBarCode = null;
        strMiddleBarCode = null;
        strBottomBarCode = null;
    }
}

NB: Есть некоторые случаи, когда вы не можете пройти по ссылке - особенно async методы и методы итератора.

Передача по ссылке также часто считается "запахом кода", и ее следует избегать везде, где это возможно. Вы можете либо создать определенный тип для хранения нескольких возвращаемых значений, либо вернуть ValueTuple вместо.

Типы кортежей - руководство по C# | Microsoft Docs[^]
public ActionResult Index()
{
    const string barcodeTopParent = "DT-COMPSTART";
    const string barcodeMiddleParent = "DB-TEST";
    const string barcodeBottomParent = "SP-SLD";
    
    var barcodes = helper.ReadBarcodeFromFile(file.FullName);
    if (barcodes.topBarCode == barcodeTopParent || barcodes.middleBarCode == barcodeMiddleParent || barcodes.bottomBarCode == barcodeBottomParent)
    {
        ...
    }
}

public (string topBarCode, string middleBarCode, string bottomBarCode) ReadBarcodeFromFile(string _Filepath)
{
    string[] barcodes = BarcodeScanner.Scan(_Filepath, BarcodeType.Code39);
    if (barcodes.Length != 0) return (barcodes[0], barcodes[1], barcodes[2]);
    return default;
}


AskalotLearnalot

Привет, спасибо за ваше время и объяснение. Второе предположение привело к той же ошибке. Однако первый из них решил проблему. По вашему опыту, есть ли у "запаха кода" побочные эффекты.

Richard Deeming

Что вы подразумеваете под "той же самой ошибкой"? Второй вариант будет только возвращать null значения, если Scan метод не вернул никаких штрих-кодов.

"Запах кода" - это то, что не обязательно неправильно, но может указывать на более глубокую проблему. В этом случае ваш метод хочет вернуть несколько значений; есть лучшие способы сделать это, чем передача по ссылке; и альтернативы приводят к коду, который более понятен и понятен.

AskalotLearnalot

Привет спасибо за повтор в обоих случаях я запустил ту же папку, которая содержит штрих-коды, так что это не проблема метода сканирования.

Richard Deeming

Попробуй перешагнуть через него. ReadBarcodeFromFile метод проверки того, что он возвращает, а затем исследует возвращаемое значение в Index метод после его возвращения.

AskalotLearnalot

так что происходит та же проблема, что и у меня в вопросе. но "запах кода" работает отлично.

Richard Deeming

Так ты говоришь, что ... ReadBarcodeFromFile метод считывает массив по крайней мере из трех строк; ни одна из строк не является null; но когда метод возвращается, и ваш if оператор выполняется, возвращаемые значения изменились на null?

Должно быть, происходит что-то еще. Возвращаемые значения кортежа работают для всех остальных.

AskalotLearnalot

Исправьте, прежде чем я перейду к последнему } в файле ReadBarcodeFromFile, если я перейду к результату действия и Гуверу над штрих-кодами var, он имеет 3 элемента. Однако strTopBarCode, strMiddleBarCode.. остается без значения после того,как он пропылесосится, а затем, когда я выхожу из метода, они получают значение null. В моем случае это были значения get, а затем, когда я выхожу из метода, им присваивается null, который я просто не знал, как передать/добавить значения обратно.

Richard Deeming

Второе решение не имеет вызываемых переменных strTopBarCode или strMiddleBarCode Так что они никак не могут быть такими . null- потому что их не существует!

AskalotLearnalot

так что эта публика (строка topBarCode, middleBarCode строку, строку bottomBarCode)
и как это будет работать для меня в заявлении if. Это ноль я не знаю как

Richard Deeming

Это кортеж значений:
Типы кортежей - руководство по C# | Microsoft Docs[^]

Это способ возврата нескольких значений из метода без необходимости писать свой собственный тип оболочки.

AskalotLearnalot

так что любая идея о том, как заставить второе решение работать. или это тот случай, когда работает только pass by ref.

Richard Deeming

Как я уже говорил, Если первое решение работает, то и второе тоже.

Вы, кажется, путаете решения и смотрите на несвязанные переменные.

AskalotLearnalot

лол, это должно сработать. Я буду делать больше копать спасибо за ваше время и помощь.

Рейтинг:
2

Richard MacCutchan

Вы не фиксируете возвращаемые значения из вызова ReadBarcodeFromFile, и дополнительные три параметра никогда не используются.

helper.ReadBarcodeFromFile(file.FullName, strTopBarCode, strMiddleBarCode, strBottomBarCode);

Код должен быть таким
Array barcodes = helper.ReadBarcodeFromFile(file.FullName) // -> not used, strTopBarCode, strMiddleBarCode, strBottomBarCode);
if (barcodes != null)
{
    // process the barcodes
}


То ReadBarcodeFromFile метод должен быть
public Array ReadBarcodeFromFile(string _Filepath)
{
    String[] barcodes = BarcodeScanner.Scan(_Filepath, BarcodeType.Code39);
    if (barcodes.Length != 0)
    {
        return barcodes;
    }
    
    return null; 
}


AskalotLearnalot

Спасибо за вашу помощь. Однако этот подход привел к тому же самому вопросу.

Richard MacCutchan

Тогда вы, должно быть, делаете что-то не так. Но поскольку вы не показали свой код, я не могу догадаться, что это может быть.