Gå til innhold

Anbefalte innlegg

Folkens, hvorfor funker ikke følgende:

 

List<lstRecord> records = new List<lstRecord>;
var kunder = from r in db.Kunder
            select r;

foreach(var rec in kunder)
 records.Add(rec);


class lstRecord : Kunder
{
   // Properties som beregner kunderelatert data
}

Vet jeg kan gjøre mye av det samme direkte i LINQ uttrykket, men alikevel, hvorfor virker det ikke?

Lenke til kommentar
Videoannonse
Annonse

Pussig. Jeg prøvde nemlig AS slik : lstRecord r = kunde as lstRecord

og det funket ikke. Men kansje det funker i LINQ uttrykket. Jeg har uansett skrevet om lstRecord klassen slik at den ikek arver, men tar Kunde som komponent i stedet. Dermed lagede jeg bare nye properties for hvert felt. Funker greit, men jeg synes det er litt sølete dog.

 

OfType<t> har jeg ikke prøvd. Må sjekke ut den og se hva den kan tilby...

Lenke til kommentar

Pass på at objektet faktisk lar seg caste. Det er vanskelig å se utifra koden din.

 

Eksempelvis:

 

class A
{
}

class B : A
{
}

class Program
{
 static void Main()
 {
   var a = new A();
   var b = new B();

   var c_b = (A)b; // Lovlig
   var c_a = (B)a; // Ulovlig! Dette vil gi exception
 }
}

Lenke til kommentar

og det er nok der jeg feiler. Klassen lstRecord er jo et derivat av Kunder slik at lstRecord inneholder mer. Men jeg trodde man kune sjongelere begge veier her så lenge de deler et minimum. Og i mitt tilfelle er jo lstRecord en utvidet versjon av Kunder. En skulel jo dermed tro at man kunne ha en lstKunder som en referanse av Kunder. Rart igrunn at det ikke går. Skjønner det ikke helt. Hadde det vært andre veien - altså at man ikek kunne hatt en Kunde record basert på lstRecord så hadde jeg forstått det. Men men, ikke alt man skall forstå her i verden ;-)

 

Anyway - ting virker nå etter at jeg skrev om litt..

 

Takker for inspill..

Lenke til kommentar

Grunnen er at oppførselen til objektet ville blitt udefinert dersom du caster oppover.

 

Sett av vi ser for oss minneområdet til den imaginære klassen Uke:

 

class Uke
{
 public int Uke { get; set; };
}[code]

class UkeDag : Uke
{
 public int Dag { get; set; };
}

UkeDag Add(UkeDag a, UkeDag b)
{
 return new UkeDag() { Uke = a.Uke + b.Uke + (a.Dag + b.Dag) / 7, Dag = (a.Dag + b.Dag) % 7 }
}

 

Hva skal skje i Add dersom a eller b egentlig er Uke, ikke UkeDag? Innholdet i Dag vil være udefinert, og programmet vil være helt uforutsigbart.

Programmet måtte ha konstruert et helt nytt objekt som fylte inn manglende informasjon, og en kan ikke forvente at .NET skal fikse dette for deg. Skal upcaste, kan du override casting for det objektet, eller lage en funksjon som genererer et korrekt objekt.

 

For å override cast kan du gjøre slik:

 

public static explicit operator UkeDag(Uke input)
{
 return new UkeDag() { Uke = input.Uke, Dag = 0 };
}

Endret av GeirGrusom
Lenke til kommentar

HDSoftware, du har nok missforstått. Forsøker meg på en basic forklaring:

 

La oss si at du har klassen Animal, og at denne har metoden MakeSound().

 

Og så har du klassan TwoLeggedAnimal, som arver fra Animal og i tillegg har metoden Walk().

 

Om du så oppretter en List<TwoLeggedAnimal> så garanterer du at alle objekter du legger inn der både kan lage en lyd og kan gå. Du kan derfor ikke legge inn andre typer dyr.

 

Oppretter du en List<Animal> kan den også inneholde TwoLeggedAnimal, fordi det eneste du har garantert er at alle objektene kan lage en lyd.

 

Gir det mening?

Endret av torbjørn marø
Lenke til kommentar

og det er nok der jeg feiler. Klassen lstRecord er jo et derivat av Kunder slik at lstRecord inneholder mer. Men jeg trodde man kune sjongelere begge veier her så lenge de deler et minimum.

 

Andre har forklart hvorfor, men tenk deg:

class A { }

class B : A { }

class C : A { }

var list = new List<B>();

// Ok, B er A, så dette må være greit!?!
List<A> generiskList = list;

// går fint, C er jo en A og må kunne legges til i en liste av A
generiskList.add(new C());

// oops, list var liste av B, men nå har vi fått en C inn her...
var first = list[0];

 

Denne typen covariance du ønsker får man i C# 4.0 om "out"-keywordet er brukt på den generiske typen. Et krav da blir at man bare kan dra objekter av den generiske typen ut, og ikke dytte den inn, så man vil ikke kunne lage en muterbar liste som benytter den funskjonaliteten

 

IEnumerable er f.eks deklarert slik, så du kan f.eks si

IEnumerable<object> list = new string[] {"hei og hopp"};

Siden vi ikke kan mutere IEnumerable kan ikke situasjonen over oppstå, og Microsoft kunnet deklarere typeargumentet "out" på IEnumerble.

Lenke til kommentar

Ja, det gir mening, men er det ikke akkurat det jeg sier da?

 

Altså, jeg har klassen Kunde, som inneholder alt om en kunde.

 

SÅ har jeg en klasse FullKunde som også inneholder funksjonalitet som forteller om kundes ordre og slikt

 

Skal ikke jeg da kunne lage et FullKunde objekt på bakgrunn av Kunde ? Eller er det kunn mulighet til å hente ut "kunde" delen av en FullKunde ? hmm - når jeg tenker etter så høres jo det fornuftig ut. Men dog...

Gitt følgende eksempel:

class Kunde
{
 string Navn
 string Adresse
 string Postnr
}

class KundeMedAdresse : Kunde
{
 string Poststed
 {
   get{ return GetPoststed(this.Postnr); }
 }
}

Dette må jo gå an..

Så kommer bruken av dette inn i koden min

var kunder = from k in db.Kunder
            select k;
// Nå vil kunder inneholde ALLE kundene
foreach(var k in kunder)
 lstKunder.Add(k);

Her vil det feile fordi man altså sier at objektet ikke vet nok om seg selv. Jeg ser ikke hvorfor i dette tilfellet.

 

@GeirG: Jeg ser jo problemstillingen med upcasting som parametere på den måten og ser hvorfor dette vil feile, men blir det det samme som mitt eksempel da?

 

Kan det være at jeg burde tenkt Extension class eller noe slikt? Er det ikek noe som heter det i C# da? Vil det løse dette? Eller er det bare en annerledes måte å se på nedarving og derav feile på samme måte?

Lenke til kommentar

Bommet kanskje litt på problemstillingen med covariance-begrepet. ikke helt det som er problemet her. (Så hvilke vei arven var...)

 

men blir det det samme som mitt eksempel da?

 

Ja, det blir et problem. Du har en liste av lstRecord, så prøver du å tilordne en Kunde, men Kunde arver ikke fra lstRecord, så den tilordningen er ikke lov.

 

En referanse av type Kunde kan peke på en lstRecord, fordi lstRecord arver fra og er en Kunde. Så en List<Kunde> kan innehodel lstRecord-objekter.

 

Men det du prøver på er motsatt. En referanse av type lstRecord kan peke ikke peke på en Kunde, fordi Kunde ikke arver fra og ikke er en lstRecord. Så en List<lstRecord> kan ikke inneholde Kunde-objekter.

Lenke til kommentar

Ja, jeg ser den... DU har rett. Hehe, ble liksom så ivrig når jeg skulle lage den klassen fordi det så så elegant ut bare å lage en utvidet klasse i stedet for å implementere hele grunnklassen. Fungerer selvsagt nå men ndet er fordi jeg har en konstruktør som tar imot Kunde og dermed fungerer det. Dog uten arving fra Kunde så klart. Kunn som komponent.

class Kunde
{
 string navn;
 string Adresse;
 string Postnr;
}

class FullKunde
{
 Kunde rec;
 string Adresse
 {
   get{ return rec.Adresse; }
   set{ rec.Adrese = value; }
 }
 etc.
 string Poststed
 {
   get{ return GetPoststed(rec.Postnr); }
 }
 public FullKunde(Kunde pRec)
 {
   rec = pRec;
 }
}

Som sagt, komponent basert, men MYE mere skriving. Kansje dere har en ide om hvordan man kan få dette til mere elegant alikevel ? ;-) Bare for morro skyld altså..

Endret av HDSoftware
Lenke til kommentar

Hvis det er Entity Framework mener jeg alle klassene er "partial" ja. Så du skal kunne bygge videre på den i en annen kildekodefil i samme assembly.

 

Inni designer.cs til datasourcen har du en autgenerert klasse som er partial:

[EtEllerAnnetEntityFrameworkAttribute]
public partial class Kunde : EntityObject 
{
  [EtAnnetEntityFrameworkAttribute]
   public string Name {...}
}

 

Da skal du kunne legge til en ny kildefil i samme prosjekt og forsette på den:

public partial class Kunde 
{
   public void SayHello() 
   {
       Console.WriteLine("Hello, " + this.Name());
   }
}

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å
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...