Tjena har ett program som tar en skärmbild och skickar sedan den till olika funktioner i andra classer för att undersökas där. Skulle nu vilja använda referensparametrar ist. för värdeparametrar eftersom jag inte ändrar något i bilden och jag tror det blir snabbare då bilden är ganska stor och tar mycket minnesutrymme. När man använder referensparametrar så måste man ange keywordet ref både vid anropet och i procedurdeklarationen. Ändra alltså till : Tackar. Kommer det bli något snabbare nu när det inte behöver tilldelas något extra minne varje gång som funktionerna anropas. Tycker det måste vara mycket smidigare med ref. Det kommer inte att bli snabbare. Problem med referensparametrar!!!
Blir det snabbare med referensparameter?
Varför får jag följande fel?
Denna kod finns i min start class
<code>
Game myGame = new Game();
myGame.MyTurn(activeWindow);
</code>
Detta finns i classen Game
<code>
public int[] MyTurn(ref Bitmap activeWindow)
{
//Något sker
}
</code>
Följande felmeddelande kommer upp:
The best overloaded method match for 'PlayerModeling.Game.MyTurn(ref System.Drawing.Bitmap)' has some invalid arguments
Argument '1': cannot convert from 'System.Drawing.Bitmap' to 'ref System.Drawing.Bitmap'
Kan någon hjälpa mig??
MVH Henrik LSv: Problem med referensparametrar!!!
<code>
Game myGame = new Game();
myGame.MyTurn(ref activeWindow); // <- Lagt till ref
</code>
Finns väl både för och nackdelar med den lösning som man valt i C#; det blir ju tydligare när man använder ref, men samtidigt får man ju skriva ett extra keyword. Sv: Problem med referensparametrar!!!
Henrik LSv: Problem med referensparametrar!!!
Vare sig du tilldelar med ref eller inte, kommer metod variablen att peka på samma objekt på heapen som parametern du skickar in.
Det finns nämligen 2 nivåer av interakation vid variabel hantering av referens typer i .NET.
När du initierar en variabel;
<code>
Bitmap myWindow;
</code>
så skapar du plats på den lokala stacken. Det är på stacken alla variabler finns. Du har ännu inte skapat ngn instans av klassen du deklarerat utan bara markerat en plats på stacken för att lagra en _adress_ till det objektet du vill åt.
När du sedan skapar objektet:
<code>
myWindow = new Bitmap;
</code>
Så allokerar du minne på heapen för att lagra ditt objekt, skapar en instans av klassen och sedan får stackvariabeln tilldelat sig adressen till objektet på heapen.
Det innebär att det nu information om objektet på två platser, det ena är på stacken vilket innehåller variabeln och en adress som pekar på objektet. Det andra är heapen där själva objektet finns.
Ok, så då har vi rett ut det, men vad har det med ref att göra?
Jo följande,
när vi skickar parametrar in till en metod by value:
<code>
int myX = 3;
Bitmap myB = new Bitmap();
this.MyFunction(myX, myB);
.
.
.
private void MyFunction(int x, Bitmap b) {}
</code>
så skapar vi en kopia av _variabeln_. Det innebär för x som är en value type, att vi faktiskt får en kopia av värdet 3. Men för Bitmapen (b) får vi en kopia av adressen till objektet som ligger på heapen. Det innebär att för valuetypes, så har du vid by val, inte en referens till det inskickade värdet, men för referens types har du, du har två stycken referenser till samma objekt på heapen.
Så det är fullt legalt att göra ändringar inuti min metod MyFunction på bitmapen och det kommer att reflekteras överallt där variabler refererar till samma objekt på heapen. Vad du däremot inte kan göra är att ändra det stack värdet som myX och myB innehåller, dvs du kan inte ändra myX värde från 3 och du kan inte tvinga myB att peka på något nytt objekt på heapen.
<code>
int myX = 3;
Bitmap myB = new Bitmap();
this.MyFunction(myX, myB);
.
.
.
private void MyFunction(int x, Bitmap b) {
x++; // Kommer bara att synas för x, inte för myX
b.someParameter = someValue // Kommer att reflekteras på myB
b = new Bitmap() // kommer bara att gälla för b, inte för myB
}
</code>
Vad gör då ref för en referensvariabel? Jo du får ju en referens till variabeln på stacken, det innebär att för myB så får du en referens till adressen till objektet på heapen.
<code>
int myX = 3;
Bitmap myB = new Bitmap();
this.MyFunction(ref myX, ref myB);
.
.
.
private void MyFunction(ref int x, ref Bitmap b) {
x++; // Kommer att räkna upp både x och myX;
b.someParameter = someValue // Kommer att reflekteras på myB och b
b = new Bitmap() // kommer att peka om myB från den initiala bilden till en helt
// ny bild;
}
</code>
Så slutsatsen är att det enda du kan kontrollera vid metodanrop för parameterar av reference type, är hurvida adressen till objektet sok skickas in, kan ändras eller inte. Du får alltid tag på samma objekt, innanför och utanför metoden.