[C#] NullReferenceExeption


(Sumek) #1

Witam,

Mam taki kod:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace Licz

{

    internal class Sumator

    {

        private static int[] arr;


        public Sumator()

        {

            arr = new int[4] { 1, 3, 6, 8 };

        }

        public int Tablica

        { get { return arr[4]; } }


        public static int Suma()

        {

            int result = 0;

            for (int i = 0; i < arr.Length; ++i)

                result += arr[i];

            return result;

        }

        public static int SumaPodziel3()

        {

            int result = 0;

            for (int i = 0; i < arr.Length; ++i)

                if (arr[i] % 3 == 0)

                    result += arr[i];

            return result;

        }

    }

    internal class Licz

    {

        private static int wartosc;


        private Licz(int w)

        {

            wartosc = w;

        }

        public int JednaWartosc

        { get { return wartosc; } }


        static void Dodaj(int liczba)

        {

            wartosc += liczba;

            Console.WriteLine("Dodaj: {0}", wartosc);

        }

        static void Odejmij(int liczba)

        {

            wartosc -= liczba;

            Console.WriteLine("Odejmij: {0}", wartosc);

        }

        static void Stan(int w)

        {

            Console.WriteLine("Stan obiektu: {0}", w);

        }

        static void Main(string[] args)

        {

            Licz obiekt = new Licz(100);

            Licz.Dodaj(10);

            Stan(wartosc);

            Licz.Odejmij(100);


            int result = 0;

            result = Sumator.Suma();

            Console.WriteLine("Suma liczb w tablicy: {0}", result);

            result = 0;

            result = Sumator.SumaPodziel3();

            Console.WriteLine("Suma liczb podzielnych przez 3: {0}", result);

            Console.ReadKey();

        }

    }

}

program wykonuję się do momentu pierwszej pętli (for (int i = 0; i < arr.Length; ++i)) for w klasie Sumator, gdzie debbuger zwraca błąd informując, że wartość jest null.


([alex]) #2
public int Tablica

        { get { return arr[3]; } }

Numeracja od zera we wszystkich C-podobnych językach.


(Tomek Matz) #3

To co wrzucił [alex] jest kompletnie bez sensu i powinieneś to usunąć z tego Swojego kodu. Natomiast jeśli chodzi o błąd, który Ci się pokazuje ... jeśli klasa posiada jakieś statyczne składowe, to należy je inicjalizować w konstruktorze statycznym. Dodaj do klasy Sumator coś takiego:

static Sumator()

{

    arr = new int[] { 1, 3, 6, 8 };

}

Wówczas kod zadziała. Sęk w tym, że pole arr nie powinno być statyczne. Przemyśl kod tej klasy, musisz ją trochę przerobić.


(Sumek) #4

@matzu

Żadne pole ze zmienną (jak w klasie Licz) nie powinno być statyczne czy tylko tablice?


(Tomek Matz) #5

@Sumek

Niejasno się wyraziłem. Zmienne statyczne możesz jak najbardziej używać. Taką zmienną może być dowolna struktura lub klasa. Ja miałem na myśli to, że w tym konkretnym przypadku użycie zmiennej statycznej jest błędem. Do Twojego problemu można podejść różnorodnie.

  1. Możesz sobie przygotować klasę, która będzie w konstruktorze otrzymywać tablicę liczb. W obrębie klasy będziesz miał zdefiniowanych szereg metod, które będą obliczać różne sumy dla tej tablicy liczb.

    using System;

    namespace ConsoleApplication

    {

    internal class Sumator
    
    {
    
        int[] arr;
    
    
        public Sumator(int[] array)
    
        {
    
            this.arr = array;
    
        }
    
    
        public int Suma()
    
        {
    
            int result = 0;
    
    
            for (int i = 0; i < arr.Length; i++)
    
                result += arr[i];
    
    
            return result;
    
        }
    
    
        public int SumaPodziel3()
    
        {
    
            int result = 0;
    
    
            for (int i = 0; i < arr.Length; i++)
    
                if (arr[i] % 3 == 0)
    
                    result += arr[i];
    
    
            return result;
    
        }
    
    }
    
    
    class Program
    
    {
    
        static void Main(string[] args)
    
        {
    
            int[] array = new int[] { 1, 3, 6, 8 };
    
            Sumator sumator = new Sumator(array);
    
    
            Console.WriteLine(sumator.Suma());
    
            Console.WriteLine(sumator.SumaPodziel3());
    
    
            array = new int[] { 1, 2, 3, 4 };
    
            sumator = new Sumator(array);
    
    
            Console.WriteLine(sumator.Suma());
    
            Console.WriteLine(sumator.SumaPodziel3());
    
    
            Console.ReadKey();
    
        }
    
    }

    }

  2. Możesz sobie przygotować klasę statyczną. W obrębie tej klasy będziesz miał zdefiniowanych szereg statycznych metod, które będą obliczać różne sumy i z których każda jako parametr będzie otrzymywać tablicę liczb.

    using System;

    namespace ConsoleApplication

    {

    internal static class Sumator
    
    {
    
        public static int Suma(int[] arr)
    
        {
    
            int result = 0;
    
    
            for (int i = 0; i < arr.Length; i++)
    
                result += arr[i];
    
    
            return result;
    
        }
    
    
        public static int SumaPodziel3(int[] arr)
    
        {
    
            int result = 0;
    
    
            for (int i = 0; i < arr.Length; i++)
    
                if (arr[i] % 3 == 0)
    
                    result += arr[i];
    
    
            return result;
    
        }
    
    }
    
    
    class Program
    
    {
    
        static void Main(string[] args)
    
        {
    
            int[] array = new int[] { 1, 3, 6, 8 };
    
    
             Console.WriteLine(Sumator.Suma(array));
    
             Console.WriteLine(Sumator.SumaPodziel3(array));
    
    
            array = new int[] { 1, 2, 3, 4 };
    
    
            Console.WriteLine(Sumator.Suma(array));
    
            Console.WriteLine(Sumator.SumaPodziel3(array));
    
    
            Console.ReadKey();
    
        }
    
    }

    }

  3. Możesz skorzystać z technologii LINQ. W ramach tej technologii udostępnionych została cała masa metod rozszerzających (takie metody możesz sobie tworzyć również samodzielnie). Wśród nich są takie, które służą do obliczania sumy.

    using System;

    using System.Linq;

    namespace ConsoleApplication

    {

    class Program
    
    {
    
        static void Main(string[] args)
    
        {
    
            int[] array = new int[] { 1, 3, 6, 8 };
    
    
            Console.WriteLine(array.Sum());
    
            Console.WriteLine(array.Where(i => i % 3 == 0).Sum());
    
    
            array = new int[] { 1, 2, 3, 4 };
    
    
            Console.WriteLine(array.Sum());
    
            Console.WriteLine(array.Where(i => i % 3 == 0).Sum());
    
    
            Console.ReadKey();
    
        }
    
    }

    }


(Sumek) #6

@matzu

Dziękuję, przestudiuję to co napisałeś:slight_smile:


(Tomek Matz) #7

@Sumek

OK, dodam jeszcze tylko, że w przypadku korzystania z LINQ trzeba myśleć co się robi.

array.Where(i => i % 3 == 0).Sum();

oraz

public static int SumaPodziel3(int[] arr)

{

    int result = 0;


    for (int i = 0; i < arr.Length; i++)

        if (arr[i] % 3 == 0)

            result += arr[i];


    return result;

}

...

Sumator.SumaPodziel3(array)

mimo tego, że zwracają ten sam wynik, nie działają dokładnie tak samo. W tym wypadku kod metody zdefiniowanej w klasie Sumator będzie szybszy (czy będą to duże różnice to już nie potrafię powiedzieć; trzeba to samemu sprawdzić). Podobne (wciąż nie takie same) działanie uzyska się w sytuacji użycia takiego kodu:

array.Sum(i => i % 3 == 0 ? i : 0);

Trzeba jednak przyznać, że ta wersja kodu wygląda już dość dziwnie i ja osobiście bym tego nie użył :stuck_out_tongue: