Struktura i metoda w niej

0

Cześć.
Mam mały problem.
Mam strukturę RGB, gdzie przechowuję jak się domyślacie, wartości składowych RGB.

struct RGB
{
        private const int MIN_RGB_VALUE = 0;
        private const int MAX_RGB_VALUE = 255;
        public int A;
        public int R;
        public int G;
        public int B;

        public RGB(int r, int g, int b)
        {
            this.A = MAX_RGB_VALUE;
            this.R = r;
            this.G = g;
            this.B = b;
        }
}

I działa ok, jednak konstruktorów w tej strukturze mam więcej. Np z parametrami (int a, int r, int g, int b), (int r, int g, int b) oraz (RGB rgb).

I teraz w każdej strukturze muszę robić tak:

public RGB(int r, int g, int b)
        {
            this.A = MAX_RGB_VALUE;
            this.R = r;
            this.G = g;
            this.B = b;
        }

        public RGB(int a, int r, int g, int b)
        {
            this.A = a;
            this.R = r;
            this.G = g;
            this.B = b;
        }

        public RGB(RGB rgb)
        {
            this.A = rgb.A;
            this.R = rgb.R;
            this.G = rgb.G;
            this.B = rgb.B;
        }

Co powoduje, że powielam cały czas jeden i ten sam kod - przypisywania.
Toteż napisałem funkcję:

public void SetRGB(int r, int g, int b)
        {
            R = r;
            G = g;
            B = b;
        }

        public void SetARGB(int a, int r, int g, int b)
        {
            SetRGB(r, g, b);
            this.SetAValue(a);
        }

Ale, gdy dodaję ją w konstruktorze to wywala mi błąd:

public RGB(int r, int g, int b)
        {
            this.SetARGB(MAX_RGB_VALUE, r, g, b);
        }

The 'this' object cannot be used before all of its fields are assigned to
Field 'Program.RGB.A' must be fully assigned before control leaves the constructor
Field 'Program.RGB.R' must be fully assigned before control leaves the constructor
Field 'Program.RGB.G' must be fully assigned before control leaves the constructor
Field 'Program.RGB.B' must be fully assigned before control leaves the constructor

Moje pytanie brzmi:
Czy można w konstruktorze struktury wywołać funkcję przypisania bez wcześniejszego powielania tego kodu?
Chciałbym po prostu stworzyć takie konstruktory:

public RGB(int r, int g, int b)
        {
            this.SetARGB(MAX_RGB_VALUE, r, g, b);
        }

        public RGB(int a, int r, int g, int b)
        {
            this.SetARGB(a, r, g, b);
        }

        public RGB(RGB rgb)
        {
            this.SetARGB(rgb.A, rgb.R, rgb.G, rgb.B);
        }

Niestety wywołuje to błędy. Jeśli w taki sposób nie jest to możliwe to dlaczego?
Dlaczego w strukturze nie jest to możliwe, a w klasie tak?

Z góry dziękuję za odpowiedź.

2

Po pierwsze, nie do końca związane z tematem -

        private const int MIN_RGB_VALUE = 0;
        private const int MAX_RGB_VALUE = 255;
        public int A;
        public int R;
        public int G;
        public int B;

Bardzo marnujesz pamięć w ten sposób. Zamiast 4 bajtów, twój kolor zajmuje 16. Dodatkowo męczysz się z maksymalnymi i minimalnymi wartościami. Z tego też powodu, robienie z tego struktury zaczyna mieć małe uzasadnienie:

Moja propozycja:

    struct RGB
    {
        public byte A;
        public byte R;
        public byte G;
        public byte B;

        public RGB(byte r, byte g, byte b)
        {
            this.A = byte.MaxValue; // i nie potrzeba stałych
            this.R = r;
            this.G = g;
            this.B = b;
        }
    }

Ew. jeśli chcesz mieś w publicznym interfejsie inty

struct RGB
{
    private byte a;
    private byte r;
    private byte g;
    private byte b;

    public RGB(int r, int g, int b)
    {
        this.a = byte.MaxValue;
        this.r = (byte)r;
        this.g = (byte)g;
        this.b = (byte)b;
    }

    public int A { get { return a; } set { a = (byte)value; } }
    public int R { get { return r; } set { r = (byte)value; } }
    public int G { get { return g; } set { g = (byte)value; } }
    public int B { get { return b; } set { b = (byte)value; } }
}

Ok, a teraz do rzeczy.

        public RGB(int r, int g, int b)
        {
            this.SetARGB(MAX_RGB_VALUE, r, g, b);
        }
 
        public RGB(int a, int r, int g, int b)
        {
            this.SetARGB(a, r, g, b);
        }
 
        public RGB(RGB rgb)
        {
            this.SetARGB(rgb.A, rgb.R, rgb.G, rgb.B);
        }

Można to rozwiązać w dość kiepski sposób tak:

        public RGB(int r, int g, int b) : this()
        {
            this.SetARGB(MAX_RGB_VALUE, r, g, b);
        }
 
        public RGB(int a, int r, int g, int b) : this()
        {
            this.SetARGB(a, r, g, b);
        }
 
        public RGB(RGB rgb) : this()
        {
            this.SetARGB(rgb.A, rgb.R, rgb.G, rgb.B);
        }

Wytłumaczenie - zanim możesz wywołać jakąś metodę struktury, wszystkie jej pola muszą być przez Ciebie wypełnione. Zapewnia to właśnie : this() które wywołuje konstruktor dymyślny wypełniający wszystko zerami.

Ale da się lepiej.
Istnieje do tego ciekawa konstrukcja, pozwalająca jednym konstruktorom wywoływać inne konstruktory tej samej klasy. Przed chwilą była zresztą zaprezentowana - this(parametry) - w taki sposób, możesz rozwiązać swój problem tak:

        public RGB(byte a, byte r, byte g, byte b)
        {
            this.A = a;
            this.R = r;
            this.G = g;
            this.B = b;
        }

        public RGB(byte r, byte g, byte b)
            : this(byte.MaxValue, r, g, b) { }

        public RGB(RGB rgb)
            : this(rgb.A, rgb.R, rgb.G, rgb.B) { }
0

Baaaaaaaaaaaaardzo dziękuję!
Naprawdę mi pomogłeś. Lepiej wytłumaczyć się tego nie dało :)

ps: O tych bajtach to ja wiedziałem ,tylko, że w tej strukturze dodawać będę liczby do składowych, przez co byte przekroczy zakres, więc jest int.

0

jeśli zamierzasz gdzieś pobierać do tej struktury wskaźnik, albo przekazywać do kodu natywnego – należałoby dodać StructLayout jeszcze:

[StructLayout(LayoutKind.Sequential)]
struct RGB
{
  ...
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1