2013-02-07 11 views
6

Cześć Chciałbym mieć klasę:jak używać gdzie dla operatorów w klasie generycznej C#?

class Matrix <T> 
    where T : // I don't know what to write here 
{ 
    T[][] elements; 
} 

chciałbym T być addable i multiplyable o + i * operatorzy

+2

Niestety, nie ma ograniczeń dla typów implementujących określonych operatorów. Istnieją obejścia, których osobiście nie użyłbym, takie jak rzutowanie na 'dynamic'. – JosephHirn

+0

[Ograniczenie tylko dla liczb całkowitych] (http://stackoverflow.com/questions/32664/c-sharp-generic-constraint-for-only-integers) z możliwym rozwiązaniem [IConvertible] (http://stackoverflow.com/a/756995/95573) – SwDevMan81

+0

mimo interesujących pytań, czy działałoby to przez niejawne określenie typów (takich jak iMatrix dla 'int' i fMatrix for' float')? – Default

Odpowiedz

1

Ponieważ nie jestem świadomy jakiegokolwiek wbudowanego rozwiązania sprawdź to:

public abstract class BaseClass 
{ 
    public static BaseClass operator +(BaseClass p1, BaseClass p2) 
    { 
     return p1 + p2; 
    } 

    public static BaseClass operator *(BaseClass p1, BaseClass p2) 
    { 
     return p1 * p2; 
    } 
} 

public class ChildClass : BaseClass 
{ 
} 

public class Matrix <T> where T : BaseClass 
{ 
    T[][] elements; 
} 

Mam nadzieję, że to pomoże.

Jednak inne typy, takie jak int, nie będą obsługiwane.

+1

jeśli jest inna klasa, która obsługuje '+' i '*', ale nie dziedziczy 'BaseClass', to nie będzie działać. Na przykład 'int' – Default

+0

@Default Rzeczywiście, dzięki za wskazanie tego. Zaktualizowałem odpowiedź, aby dodać to ograniczenie. –

1

Może być w ten sposób będzie pomocne dla kogoś. Możesz to poprawić, dodając, multiplikuj funkcje w klasie biblioteki tkanin.

UPDATE Może być wprowadzenie operatorów z JerKimball postu w counstructor

class Matrix <T> 
{ 
    T[][] elements; 

    public Matrix(Func<T, T, T> add, Func<T,T,T> multiplicate) 
    { 
     this.Add = add; 
     this.Mult = multiplicate; 
    } 

    public Matrix<T> operator +(Matrix<T> p1, Matrix<T> p2) 
    { 
     // correct this 
     var t = Add(p1.elements[0][0], p2.elements[0][0]); 
     return this; 
    } 

    public Matrix<T> operator *(Matrix<T> p1, Matrix<T> p2) 
    { 
     // correct this 
     var t = Mult(p1.elements[0][0], p2.elements[0][0]); 
     return this; 
    } 

    private Func<T, T, T> Add { get; set; } 

    private Func<T, T, T> Mult { get; set; } 
} 

static void Main(string[] args) 
{ 
    var m1 = new Matrix<int>((x,y) => x + y, (x,y) => x * y); 
    var m2 = new Matrix<int>((x, y) => x + y, (x, y) => x * y); 
} 

UPDATE 2

tylko zapewnić dostęp do własności takiego:

public T[][] Elements { get; set; } 

i można zrób to:

m1.Elements[0][0] = 10; 
var m3 = new Matrix<int?>((x, y) => x + y, (x, y) => x * y); 
m3.Elements[0][0] = null; 
+0

w ten sposób nie mogę podać wartości elementu (jak 0 lub dowolna liczba, również nie mogę rzucić ich do int lub dowolnego typu nieululowanego) –

+0

Czy możesz podać przykład, czego nie możesz zrobić? – gabba

2

Gorąco polecam spojrzeć na „MiscUtil” biblioteki z panów Skeet i Gravell:

http://www.yoda.arachsys.com/csharp/miscutil/

Zawarte w to niesamowite „podmioty generyczne matematyczne” Wdrożenie, które powinny dopasuj się ładnie do twoich prób stworzenia ogólnej macierzy matematycznej. Właściwie to przypomina mi (trochę) pytona i jak obsługuje bezpośrednie odwoływanie się do funkcji operatora.

(bok do @ Jon-Skeet: jakaś szansa na to toruje sobie drogę do Nuget?)

Niektóre przykłady zwyczajów od swoich testów:

double sumOperator = 0; 
for (int i = 0; i < COUNT; i++) 
{ 
    sumOperator = Operator.Add(sumOperator, rand.NextDouble()); 
} 

int sumOperator = 0; 
for (int i = 0; i < COUNT; i++) 
{ 
    sumOperator = Operator.Add(sumOperator, rand.Next(MAXVALUE)); 
} 
1

To nie jest możliwe, ponieważ w warunkach swobodnych typu rodzajowego przyjmuje się, że jest typu Object, który nie definiuje operatorów arytmetycznych. Dlatego wydaje się, że musisz określić interfejs.

Ale prymitywne typy (Int32, podwójne, itp) określają operacje arytmetyczne skutecznie jako metod statycznych (faktycznie kompilator traktuje je specjalnie i generuje inline code) oraz interfejs w języku C# nie można definiować metody statyczne (choć projekt CLR faktycznie pozwala na to). W związku z tym w języku C# nie można zapisać interfejsu, który spełnia wymagania związane z obsługą operacji arytmetycznych; nawet jeśli można to zapisać, typy pierwotne nie odziedziczą go, więc nadal by nie działał.

Wynik końcowy jest taki, że nie ma sposobu, aby zrobić to, co chcesz w C#.

Jeśli nie spróbować, pojawi się błąd podobny do

Operator '+' cannot be applied to operands of type 'T' and 'T' 

Jeśli do wyszukiwania w sieci dla tej wiadomości, znajdziesz różne dyskusje na temat możliwych obejściach.

Powiązane problemy