簡體   English   中英

c#中按值傳遞數組

[英]Passing array by value in c#

據我了解,在c#傳遞的默認類型或參數是按值傳遞的。 因此不需要聲明。 但是當我嘗試運行以下代碼時,我在 Main 中的A矩陣正在被類DecompositionFactorize()方法中對dMatrixU所做的操作修改。 我敢肯定,問題是在的構造Decomposition時,我只是assing AdMatrixU的參考A被分配的,而不是價值。 因此,我關於如何避免這種情況的問題,我發現的只是如何通過引用傳遞參數。 同樣,據我所知,按值傳遞參數不需要修飾符。 我哪里錯了?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using LinearEquations;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            double[,] A = new double[,]
              { { 1, 1, 1  }  ,
                { 4, 3, -1 }  ,
                { 3, 5, 3  } };
            double[] B = new double[] {1,6,4};
            Decomposition lu = new Decomposition(A,B);
            lu.Factorize();
            PrintMatrix(A,"A:");
            PrintVector(B,"B:");
            PrintMatrix(lu.L,"L:");
            PrintMatrix(lu.U,"U:");
            PrintVector(lu.D,"D:");
        }
        public static void PrintMatrix(double[,] M, String Title = "Matrix: ")
        {
            Console.WriteLine(Title);
            for(int i = 0; i<M.GetLength(0); i++)
            {
                for(int j = 0; j<M.GetLength(1);j++)
                {
                    Console.Write(M[i,j]+"\t");
                }
                Console.Write("\n");
            }
            Console.Write("\n");
        }
        public static void PrintVector(double[] V, String Title = "Vector: ",bool AsRow = true)
        {
            String str = (AsRow)? "\t" : "\n";
            Console.WriteLine(Title);
            for(int i = 0; i<V.GetLength(0); i++)
            {
                Console.Write(V[i]+str);
            }
            Console.WriteLine("\n");
        }
    }
}

namespace LinearEquations
{
    public class Decomposition
    {
        // Fields
        private double[,] dMatrixA;  // Parameter in A*X=B
        private double[] dVectorB;  // Parameter in A*X=B
        private double[] dVectorX;  // Result wanted in A*X=B
        private double[,] dMatrixU; // A splits into L and U
        private double[,] dMatrixL; // L is used to calculate D in L*D=B
        private double [] dVectorD; // D is used to calculate X in U*X=D

        // Properties
        public double[,] A
        {
            get { return dMatrixA; }
            set { dMatrixA = value; }
        }
        public double[] B
        {
            get { return dVectorB; }
            set { dVectorB = value; }
        }
        public double[] X
        {
            get { return dVectorX; }
            set { dVectorX = value; }
        }
        public double[,] L
        {
            get { return dMatrixL; }
            set { dMatrixL = value; }
        }
        public double[,] U
        {
            get { return dMatrixU; }
            set { dMatrixU = value; }
        }
        public double[] D
        {
            get { return dVectorD; }
            set { dVectorD = value; }
        }

        // Constructor
        public Decomposition(double[,] A, double[] B)
        {
            dMatrixA = A;
            dVectorB = B;
            dVectorX = new double[B.Length];
            dMatrixU = A;
            dMatrixL = new double[A.GetLength(0),A.GetLength(1)];
            dVectorD = new double[B.Length];
        }

        // Split A into L and U
        public void Factorize()
        {
            // Iterate per each row
            for(int i = 0; i<dMatrixU.GetLength(0); i++)
            {
                // For all the rows make element i equals 0
                for(int j = i+1; j<dMatrixU.GetLength(0);j++)
                {
                    // Factor that assures substraction makes 0
                    dMatrixL[1,1] = dMatrixU[j,i] / dMatrixU[i,i];

                    // Iterate per each column
                    for(int k = 0; k<dMatrixU.GetLength(1);k++)
                    {
                        dMatrixU[j,k] = dMatrixU[j,k] - dMatrixU[i,k]*dMatrixL[1,1];
                    }
                }
            }
        }

    }
}

據我所知,在 c# 中傳遞的默認類型或參數是按值傳遞的。

不幸的是,它有點復雜,並且還有一些 execptions:

Decomposition這樣的引用類型,您可以通過制作引用的副本來提交。 不幸的是,這意味着兩者仍然在內存中引用同一個實例 因此,盡管進行了復制操作,但它是按引用調用的。

對於像Intdouble這樣的值類型及其別名,通常會創建一個副本。 我不知道任何情況下沒有,但我以前在這些事情上是錯的。 所以它們是按值調用的。

最后, String和其他一些引用類型在設計上是不可變的。 這樣做的好處是它們在這方面的行為有點像值類型。 你交了一個引用,但實例本身不能改變。 代碼只能在內存中創建一個具有不同值的新實例。 因此,盡管移交了字面引用,但它的工作方式有點像按值調用。

您的具體情況

數組是非常明確的引用類型。 將它們交給一個沒有副作用的函數,需要適當的克隆。 如果是引用類型的數組,那么克隆一定是深的。

在您的情況下,您有值類型的數組。 如果要避免按引用調用的副作用,則必須克隆這些數組。 但是,由於 double 是值類型,因此這種克隆可能會很淺 不需要深度克隆。

與 Java 不同,沒有專用的 Clone() 方法。 我不確定為什么會這樣。 但是,您通常可以通過構造函數使用一個集合來初始化另一個集合。 或者他們甚至有一個像Array.Copy()這樣的函數,正如 TheBatman 指出的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM