Gå til innhold

C#: Legge sammen to elementer fra generisk liste?


Anbefalte innlegg

Det er mulig at jeg står overfor et "trick question" her:

 

Jeg har laget en rullerende liste i en generisk klasse.

 

class MyList <T>

 

med metoder for å legge til og returnere elementer.

 

Denne bruker jeg med instanser av ulike typer (tall, strenger etc)

 

Så langt alt bra. Men så sier oppgaven (det er fra et gammelt kurs jeg repeterer dette) at jeg skal lage en hjelpeklasse med metoder som legger sammen og subtraherer to elementer.

 

Så jeg forsøker meg med:

 

class Utilities <T>
....
public T AddTwoItems(T item1, T item2)
{ return item1 + item2; }

 

Men siden T ikke er definert får jeg ikke lov å plusse dem. ("Operator '+' cannot be applied to operands of type 'T' and 'T'")

 

Jeg kan selvsagt(?) overstyre for spesielle typer, men hva ellers kan jeg gjøre? Er det noe jeg overser? Kan jeg eventuelt stille som betingelse at T implementerer '+' på noen måte?

 

Repitisjon er noe herk, da får du vite hvor godt du fulgte med i første omgang... ;)

 

Geir :)

Endret av tom waits for alice
Lenke til kommentar
Videoannonse
Annonse

Strengt tatt er det ikke mulig på noen enkel måte. Er du sikker på at det er det som er oppgaven?

 

Jeg ville gått utifra at oppgaven går ut på å legge sammen to lister, ikke elementene i dem, ettersom .NET ikke kan vite run-time om verdiene støtter + eller -. De fleste typer gjør det ikke.

Endret av GeirGrusom
Lenke til kommentar

Bare sånn for å ha sagt det, du kan ikke si noe om implisitte operatorer på en generisk klasse. Det som funker her, og er enkelt er som følger:

 

public T AddTwoItems(T item1, T item2)

{

dynamic aa=a;

dynamic bb=b;

return aa+bb;

}

 

Det vil feile om du ikke har noe try catch og typen faktisk ikke støtter + riktignok.

Endret av The Jackal
Lenke til kommentar

Nei, du constrainet til IAdd<T> som er et interface som ikke eksisterer. Jeg regnet med at du startet med en annen løsning uten dynamic dispatch (som er djevelen) og deretter endret mening.

 

Stemmer det...jeg ville gjort det egentlig om det var snakk om reference types/mine egne klasser for å komme utenom dynamic. Men akkurat her var det snakk om valuetypes, så da er dette den enkleste løsningen. Bare for å ta med den alternative løsningen:

 

   public interface IAdd<T>
   {
    T Add(T item);
   }
   public class Utilities<T> where T : IAdd<T>
   {
    public T AddTwoItems(T a, T b)
    {
	    return a.Add(b);
    }
   }

Lenke til kommentar

Jeg har en løsning i hodet som unngår dynamic dispatch, og som er type-safe :) Men den er mindre triviell.

 

Man kan bruke System.Linq.Expressions og kompilere en delegate statisk for å addere.

 

public static class Utilities<T>
{
	private static readonly Func<T, T, T> adder;
	static Utilities()
	{
		var arg1 = Expression.Parameter(typeof (T));
		var arg2 = Expression.Parameter(typeof (T));
		Expression<Func<T, T, T>> exp =
		Expression.Lambda<Func<T, T, T>>(Expression.Add(arg1, arg2), arg1, arg2);
		adder = exp.Compile();
	}
	public static T AddTwoItems(T a, T b)
	{
		return adder(a, b);
	}
}

(utestet)

 

edit: usikker på om dette faktisk er bedre enn dynamic dispatch...

Endret av GeirGrusom
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...