Klasy zawierające typy uniwersalne.

0

posiadam klasę

public class MyClass
    {
        myType core;

        public MyClass()
        {
            myType = new MyType();
        }
    }

Obiekty klasy MyClass będą tworzone w różnych okolicznościach a także klasa myType, której obiekt zadeklarowany jest w klasie MyClass będzie różna.
np:

public class MyClass
    {
        myType1 core;
.....


public class MyClass
    {
        myType2 core;
.....

public class MyClass
    {
        myType3 core;
.....

Wszystkie inne pola będą bez zmian (typy). Czy da się przekształcić ww. klasę aby korzystać z typów uniwersalnych <T> i przekazywać dany typ do tworzonego obiektu jako typeof(danaKlasa) (bądź w inny sposób). Będę wdzięczny za podpowiedzi, co do budowy klasy, ponieważ nie widzi mi się tworzyć naście klas, które tylko będą się różniły typem jednej składowej.

pozdrawiam
J.

1

przekazywać dany typ do tworzonego obiektu jako typeof(danaKlasa)

W taki sposób jaki (jeśli dobrze czytam) rozumiesz - nie. Typ generyczny musi być znany na etapie kompilacji.

Będę wdzięczny za podpowiedzi, co do budowy klasy, ponieważ nie widzi mi się tworzyć naście klas, które tylko będą się różniły typem jednej składowej.

A zwykła klasa generyczna nie wystarczy?
Ewentualnie użyj fabryki zwracającej ci po typie.

0

public class MyClass<T>
{
T core;

    public MyClass()
    {
        myType = new MyType();
    }
}

nie używałem nigdy klas generycznych, może za wyjątkiem kolekcji. Czyli powyższe może być? zaraz przetestuje, dzięki ;p

0
unitype napisał(a)

public class MyClass<T>
{
T core;

    public MyClass()
    {
        myType = new MyType();
    }
}

nie używałem nigdy klas generycznych, może za wyjątkiem kolekcji. Czyli powyższe może być? zaraz przetestuje, dzięki ;p

Zawszę napiszę jakąś głupotę bez kompilacji, hmm poprawka:

public class MyClass<T>
{
T core;

    public MyClass()
    {
        core = new T();
    }
}

ale.. nie da się,
Error 1 Cannot create an instance of the variable type 'T' because it does not have the new() constraint C:\Users\user\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs 21 20 ConsoleApplication1

1

Ach... :D Trzeba było pisać od razu a nie mieszać ;)

public class MyClass<T>
 where t: new()
{
}
0
MSM napisał(a)

Ach... :D Trzeba było pisać od razu a nie mieszać ;)

public class MyClass<T>
 where t: new()
{
}

a da się także dodać informacje o tym, że T może być nullable?
btw, jakby ktoś miał dobre źródło wiedzy an temat typów generycznych (nie kolekcji generycznych) oraz używania słowka "where", będę wdzięczny.

0
unitype napisał(a)

a da się także dodać informacje o tym, że T może być nullable?

mozesz zawezic do klas, wiec to nie do konca to samo

unitype napisał(a)

btw, jakby ktoś miał dobre źródło wiedzy an temat typów generycznych (nie kolekcji generycznych) oraz używania słowka "where", będę wdzięczny.

MSDN, specyfikacja jezyka C# (do pobrania takze ze strony ecma)

1

a da się także dodać informacje o tym, że T może być nullable?

public class MyClass<T>
 where t: class
{
}

jakby ktoś miał dobre źródło wiedzy an temat typów generycznych (nie kolekcji generycznych) oraz używania słowka "where", będę wdzięczny.

on i on mają.

edit: &()%^&( ubiegłeś mnie massther ;)

0
massther napisał(a)
unitype napisał(a)

a da się także dodać informacje o tym, że T może być nullable?

mozesz zawezic do klas, wiec to nie do konca to samo

unitype napisał(a)

btw, jakby ktoś miał dobre źródło wiedzy an temat typów generycznych (nie kolekcji generycznych) oraz używania słowka "where", będę wdzięczny.

MSDN, specyfikacja jezyka C# (do pobrania takze ze strony ecma)

mam SDK do NET 3.5 ale znaleźć dobry sample to sztuka cierpliwości.

Czyli generalnie zapis

core=null;

nigdy nie będzie miał prawa bytu?

0

last one, a da się "łączyc" warunek T:new() oraz T:class ?

0

No jak chcesz, żeby core=null nie miało prawa bytu, skoro sam napisałeś, że chcesz, by było to możliwe?

Napisz może co chcesz właściwie osiągnąć.

Drugie pytanie: postaw przecinek. New() musi być na ostatnim miejscu.

0
Rev.pl napisał(a)

No jak chcesz, żeby core=null nie miało prawa bytu, skoro sam napisałeś, że chcesz, by było to możliwe?

Napisz może co chcesz właściwie osiągnąć.

Drugie pytanie: postaw przecinek. New() musi być na ostatnim miejscu.

Hmm moje zapytanie było w celu potwierdzenia, czy wyciągnąłem dobre wnioski. Ale jednak były nieprawidłowe.

kompilator na to:"ConsoleApplication1.MC' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ConsoleApplication1.MyClass<T>' "

Czyli rozumiem, że nie konstuktor w klasie, która będzie podana jako T musi być bezparametrowy?
Chyba, że są jakieś obejścia..

btw, zbudowałem taki kod do testów funkcjonalności:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass<MC> c = new MyClass<MC>();
        }
    }

    public class MyClass<T> where T : class, new()
    {
        T core = null;

        public MyClass()
        {

            core.ToString();
            Console.Read();
        }
    }

    public sealed class MC
    {
        int a;
        string b;

        public MC(int la, string lb)
        {
            a = la;
            b = lb;
        }
    }

}
0

A co chcę osiągnąć? Hmm odpowiedź jest w 1 poście. Ale jeżeli klasy generyczne, a raczej klasy, które będą przekazywane jako typ do klas generycznych nie mogą posiadać parometrowych konstruktorów, to nie wiem jakie mam wyjście.

0

Obiekty klasy MyClass będą tworzone w różnych okolicznościach a także klasa myType, której obiekt zadeklarowany jest w klasie MyClass będzie różna.

Nie no, naprawdę, oświeciłeś mnie.

Napisz ogólniej co chcesz zrobić to może w końcu ktoś skieruje cię na dobrą drogę, a tak na siłę próbujesz robić coś, czego nie rozumiesz i to jeszcze kompletnie bezsensownie (ten kod, który wkleiłeś jako ostatni jest bezsensowny). Chcesz napisać klasę do wywoływania .ToString na różnych obiektach :/?

0
Rev.pl napisał(a)

Obiekty klasy MyClass będą tworzone w różnych okolicznościach a także klasa myType, której obiekt zadeklarowany jest w klasie MyClass będzie różna.

Nie no, naprawdę, oświeciłeś mnie.

Napisz ogólniej co chcesz zrobić to może w końcu ktoś skieruje cię na dobrą drogę, a tak na siłę próbujesz robić coś, czego nie rozumiesz i to jeszcze kompletnie bezsensownie (ten kod, który wkleiłeś jako ostatni jest bezsensowny). Chcesz napisać klasę do wywoływania .ToString na różnych obiektach :/?

Nie zrozumiałeś mnie ;p A raczej napisałem za mało, aby cokolwiek poprawnie zinterpretować.
Klasa którą mam zamiar zbudować będzie miała zupełnie inne zastosowanie, niż używanie ToString() na składowych.

Dałem ToString() bo jako pierwsza wpadłą mi do głowy, chciałem po prostu odwołać się do obiektu w najprostszy sposób, aby sprawdzić czy obiekt jest utworzony (mogłem ifa czy null) ale to string się szybciej pisze ;p

Domysłam się, że kod który zamieściłem jako ostatni jest kompletnie bezsensowny, ale to tylko test klasy generycznej, która może/musi mieć pewne cechy.

Sprawa wygląda docelowo tak:

Posiadam klika klas, dziedziczącym po pewnym interfejsie, przykładowo w skrócie:

class CoreA:ICore{}
class CoreB:ICore{}
class CoreC:ICore{}
class CoreD:ICore{}
itd..

Oraz posiadam pewną klasę, która jako prywatną składową posiada obiekt typu jednego z powyższych.
Przykładowo:

class MyClass1
{
CoreA core;

 public MyClass1(parametry)
{kod}

 reszta składowych

}

Lecz CoreA w klasie powyżej może być równie dobrze CoreB, itp.
W prawdzie mógłbym użyć ICore core;, ale nie wykluczam, że owa klasa (MyClass1) będzie miała dostęp również do innych metod, które zawiera CoreA, itp a których nie ma w ICore.

Dlatego wpadłem na pomysł klas generycznych aby zaimplementować zmienność typów pola core.
Ale nie wiem jak wybrnąć z bezparametrowych konstruktorów. Może znacie lepsze obejscie..

1

Posiadam klika klas, dziedziczącym po pewnym interfejsie, przykładowo w skrócie:

To dodaj jak człowiek: ;)

 where T: ICore

Ale nie wiem jak wybrnąć z bezparametrowych konstruktorów.

Interfejsy z tego co pamiętam (ale może się mylę) nie mogą zawierać konstruktorów.
W takim razie dodaj do nich po prostu statyczną metodę zwracającą obiekt danej klasy.
(albo przemyśl, jak pisałem, factory. Może akurat będzie pasował do twojego projektu)

0
MSM napisał(a)

Posiadam klika klas, dziedziczącym po pewnym interfejsie, przykładowo w skrócie:

To dodaj jak człowiek: ;)

 where T: ICore

Ale nie wiem jak wybrnąć z bezparametrowych konstruktorów.

Interfejsy z tego co pamiętam (ale może się mylę) nie mogą zawierać konstruktorów.
W takim razie dodaj do nich po prostu statyczną metodę zwracającą obiekt danej klasy.
(albo przemyśl, jak pisałem, factory. Może akurat będzie pasował do twojego projektu)

tak, interfejsy nie mogą zawierać konstruktorów, ale klasy CoreA:ICore owszem ;p
co do factory'ów, nie wiem co to jest, ale poczytam

dzięki za poświęcony czas

0
unitype napisał(a)

Czyli rozumiem, że nie konstuktor w klasie, która będzie podana jako T musi być bezparametrowy?

Ale nie wiem jak wybrnąć z bezparametrowych konstruktorów. Może znacie lepsze obejscie..

Zdziwiony?
Sam przecież to wymuszasz pisząc: "where T: new()".

W prawdzie mógłbym użyć ICore core;, ale nie wykluczam, że owa klasa (MyClass1) będzie miała dostęp również do innych metod, które zawiera CoreA, itp a których nie ma w ICore.

A skąd klasa MyClass1 będzie wiedziała o tych innych metodach z CoreA, skoro nie będzie wiedziała, że ten obiekt jest typu CoreA? I tak będzie musiała sprawdzać typ i rzutować aby móc wywołać metodę. Jest to bardzo brzydkie, ale wykonalne.

Wydaje mi się, że schrzaniłeś projekt i próbujesz znaleźć obejście problemu, który sam sobie stworzyłeś, a który tak naprawdę nie istnieje.

using System;

namespace CostamTest
{
    interface ICore
    {
        void MyMethod();
    }

    class CoreA : ICore
    {
        #region IInterface Members

        public void MyMethod()
        {
            Console.WriteLine("Dupa");
        }

        #endregion

        public void OtherMethodA()
        {
            Console.WriteLine("Inna dupa");
        }
    }

    class CoreB : ICore
    {
        #region IInterface Members

        public void MyMethod()
        {
            Console.WriteLine("Cycki");
        }

        #endregion

        public void OtherMethodB()
        {
            Console.WriteLine("Inne cycki");
        }
    }

    class MyClass1<T>
        where T : ICore
    {
        ICore core;

        public MyClass1(T core)
        {
            this.core = core;
        }

        public void DoWithICore()
        {
            this.core.MyMethod();
        }

        public void DoWithClass()
        {
            if (this.core is CoreA)
            {
                (this.core as CoreA).OtherMethodA();
            }
            else if (this.core is CoreB)
            {
                (this.core as CoreB).OtherMethodB();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass1<CoreA> a = new MyClass1<CoreA>(new CoreA());
            a.DoWithICore();
            a.DoWithClass();
            MyClass1<CoreB> b = new MyClass1<CoreB>(new CoreB());
            b.DoWithICore();
            b.DoWithClass();
            Console.ReadLine();
        }
    }
}
0
somekind napisał(a)
unitype napisał(a)

Czyli rozumiem, że nie konstuktor w klasie, która będzie podana jako T musi być bezparametrowy?

Ale nie wiem jak wybrnąć z bezparametrowych konstruktorów. Może znacie lepsze obejscie..

Zdziwiony?
Sam przecież to wymuszasz pisząc: "where T: new()".

W prawdzie mógłbym użyć ICore core;, ale nie wykluczam, że owa klasa (MyClass1) będzie miała dostęp również do innych metod, które zawiera CoreA, itp a których nie ma w ICore.

A skąd klasa MyClass1 będzie wiedziała o tych innych metodach z CoreA, skoro nie będzie wiedziała, że ten obiekt jest typu CoreA? I tak będzie musiała sprawdzać typ i rzutować aby móc wywołać metodę. Jest to bardzo brzydkie, ale wykonalne.

  1. Jak wspomniałem, nie miałem styczności z klasami generycznymi, i np dla mnie nie jest to oczywiste, że taki zapis wymusza owe zachowanie
    Czy w takim razie tylko dziedzicząc po klasie, która posiada konstruktor z parametrami mogę osiągnąc ww. zachowanie?

  2. MyClass1 będzie klasą abstrakcyjną, więc np MyClassA1, MyClassA2 (dziedziczące po MyClass1) etc będą bazowały na zbiorze metod dostarczanych przez Core ( w tym przypadku wersja A).

1 pytanie to czysta ciekawość, ponieważ mogę tworzyć składowe klas dziedziczących po ICore w metodach tej klasy.

1
  1. Jak wspomniałem, nie miałem styczności z klasami generycznymi, i np dla mnie nie jest to oczywiste, że taki zapis wymusza owe zachowanie
    Czy w takim razie tylko dziedzicząc po klasie, która posiada konstruktor z parametrami mogę osiągnąc ww. zachowanie?

Od początku. Typ generyczny może być dowolnym istniejącym typem. Dlatego właśnie kompilator (i ty) nie może nic zakładać. Jeśli wiesz (albo tego potrzebujesz) że typ będzie miał np. bezparametrowy konstruktor to informujesz o tym klasę i wtedy spokojnie możesz go używać - bo klasa WIE że on istnieje. W przeciwnym wypadku nie możesz.

  1. MyClass1 będzie klasą abstrakcyjną, więc np MyClassA1, MyClassA2 (dziedziczące po MyClass1) etc będą bazowały na zbiorze metod dostarczanych przez Core ( w tym przypadku wersja A).

To już wcale nie rozumiem problemu.
where T:ICore, MyClass1
A jeśli potrzebujesz konkretnych metod z konkretnej klasy to gdzie tutaj generyczność 0_o

0
unitype napisał(a)
  1. Jak wspomniałem, nie miałem styczności z klasami generycznymi, i np dla mnie nie jest to oczywiste, że taki zapis wymusza owe zachowanie

TY napisałeś "where T: new()", więc nie możesz się tłumaczyć, że nie wiesz, co to znaczy.

The type argument must have a public parameterless constructor. When used in conjunction with other constraints, the new() constraint must be specified last.

Źródło: http://msdn.microsoft.com/en-US/library/d5x73970%28v=VS.80%29.aspx

Czy w takim razie tylko dziedzicząc po klasie, która posiada konstruktor z parametrami mogę osiągnąc ww. zachowanie?

Jakie zachowanie?
I co Ci nie pasuje w moim kodzie? Bo na tyle, na ile zrozumiałem Twój problem, to jest on pewnym rozwiązaniem.

MSM napisał(a)

A jeśli potrzebujesz konkretnych metod z konkretnej klasy to gdzie tutaj generyczność 0_o

Wiesz, ja już też przestałem rozumieć o co tu chodzi. :|
Dopóki autor nie opisze i nie narysuje co chce osiągnąć chyba nie będziemy mu w stanie pomóc.

0
somekind napisał(a)
unitype napisał(a)

Czy w takim razie tylko dziedzicząc po klasie, która posiada konstruktor z parametrami mogę osiągnąc ww. zachowanie?

Jakie zachowanie?

i do tego, jakie dziedziczenie? konstruktory nie sa dziedziczone..

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