Új hozzászólás Aktív témák
-
pmonitor
aktív tag
válasz Alexios #10050 üzenetére
Akkor már csak 1 kérdésem van: mi a bánatnak ennyiféle ciklus, ha tökmind1, hogy melyiket használjuk? Elég lenne a while(), 'oszt jó napot! Ennek ellenére van a while(), van a do..while, van a for(), és még ráadásul ott van ez a foreach() is. Minek?
http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
pmonitor
aktív tag
válasz Alexios #10050 üzenetére
a hivatalos msdn c# language spec doksi, ez egyértelműen írja hogy All struct types implicitly inherit from the class System.ValueType
1: És ha a hivatalos msdn doksi azt írja, hogy ugorj a kútba, akkor beleugrasz?
2: Szted. az érték típusoknak van referenciájuk?http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
Tomi_78
tag
És az miért van, hogy ha én maximumra állítom a játéktér ablakméretét, akkor induláskor a játékelemek az eredeti, 800*600-as beállításhoz alkalmazzák a koordinátáikat?
Tehát az alábbi kód beállítja ugyan a képernyő kitöltésére a pályát, de ha pl. az a_jatekos példány lekérdezi magának induláskor a Width és Height koordinátákat, azok mintha még mindig 800 és 600 lennének, holott nálam 1600*900-nak kellene lenniük (kiírva is annyi), de mégis a közép elhelyezés helyett balra fel kerül a játékelem:InitializeComponent();
WindowState = FormWindowState.Maximized;
Size = new Size(Width,Height);a_jatekos = new Jatekos();
a_jatekos.kepe = jaturhajokepe1;
a_jatekos.xhely = Width/2+a_jatekos.kepe.Width;
a_jatekos.yhely = Height-a_jatekos.kepe.Height*2; -
-
Tomi_78
tag
Úgy látszik, a WindowState nem állítja át az ablak Width és Height értékeit - legalábbis ha ezt a kódot alkalmazom és kiíratom az ablszel és ablmag változók értékeit, azok még mindig a 800*600-at mutatják, amik az InitializeComponent()-ben is be vannak állítva:
InitializeComponent();
WindowState = FormWindowState.Maximized;
Size = new Size(Width,Height);
ablszel=Size.Width;
ablmag=Size.Height; -
Tomi_78
tag
Sziasztok!
Egyedi képeket már tudok kezelni (betölteni és megjeleníteni) a C#-pal, de jó volna tudnom kezelni képcsíkokat.
Van erre lehetőség és ha igen, hogyan, milyen utasítás alkalmas arra, hogy egy nagy képből kinyerjem annak alképeit és hozzárendeljem egy bitmap-hoz? -
Tomi_78
tag
Sziasztok!
Kis programomat teljes képernyős módban futtatom az alábbi kóddarab segítségével:
InitializeComponent();
Viszont lent a Windows 10 tálcája belóg a programablakba, így van úgy, hogy a grafikai elemeket is takarja, ha éppen oda helyeződnek. Kerestem a Google-lal arra, hogy hogyan lehetne eltüntetni a Tálcát C#-ban, de nem találtam semmit ezzel kapcsolatban. Aztán most próbálom megnézni, hogy mennyi a képernyőfelbontás magassága, hogy abból kivonva valami értéket megkapjam a Tálca nélküli részt, de nem találok ilyen felbontásérték visszaadó függvényt, utasítást.
WindowState = FormWindowState.Maximized;
Size=new Size(Screen.PrimaryScreen.WorkingArea.Width,Screen.PrimaryScreen.WorkingArea.Height);
Az is érdekes, hogy a Windows-ban megnézve a képernyőfelbontást, az 1920*1080, tehát 1080 képpont a magasság, viszont a C#-ot sehogysem bírom rávenni ezen érték kiírására, mert mindig 864-et mutat valamiért, mikor az egér Y koordinátáját kérdezem le, és a képernyő alján van, vagy így:e.Graphics.DrawString("Egér Yhely: "+Cursor.Position.Y+"-"+Screen.PrimaryScreen.Bounds.Height.ToString(),this.Font,new SolidBrush(Color.Black),2,2);
Valaki el tudná magyarázni nekem erre a megoldást? Tehát:
1. Miért 864 képpont nálam C#-ban a képernyőmagasság 1080 helyett?
2. Hogyan kaphatom meg csak a hasznos területet a képernyőből, tehát a Tálca és a felső menüsor magassága nélküli értéket? -
dqdb
nagyúr
válasz Tomi_78 #10060 üzenetére
1. Miért 864 képpont nálam C#-ban a képernyőmagasság 1080 helyett?
Mert Windowsban 125%-ra állítottad a scalinget, az alkalmazásod pedig nem jelzi, hogy high DPI támogatással bír, így a Windows a tényleges helyett a scalinggel korrigált virtuális értéket adja át neked2. Hogyan kaphatom meg csak a hasznos területet a képernyőből, tehát a Tálca és a felső menüsor magassága nélküli értéket?
A felső menüsor, az ablakfejléc és a keret az alkalmazás saját felségterülete, azzal azt kezd, amit akar, azok az ablakméreten belül vannak. A tálca nélküli téglalapot aScreen.WorkingArea
propertyben találod.Egy ablak két része szedhető szét: client area, ami a hasznos felülete (a lenti képen pirossal jelezve) és a non-client area, ahová a körítés (fejléc, menü, keret) kerülnek. A hasznos területet a Control.ClientRectangle propertyvel tudod lekérdezni, ez azt a téglalapot adja vissza, ami az ablakod szabadon használható területe.
Érdemes megjegyezni, hogy több monitor esetében mind a DPI, mind a tálca mérete, mind a rendelkezésre álló terület eltérhet, és az alkalmazásodat monitorok között dobálva ez indítás után bármikor bekövetkezhet, szóval érdemes a változásokról érkező eseményeket lekezelni.
[ Szerkesztve ]
tAm6DAHNIbRMzSEARWxtZW50ZW0gdmFka5RydIJ6bmkuDQoNClOBc4Ek
-
Tomi_78
tag
Köszönöm a választ, Dqdb!
Ez alapján elindulva a Tálca tetejét a következő kóddarabbal találtam meg (remélhetőleg):Screen.PrimaryScreen.WorkingArea.Height-(Screen.PrimaryScreen.WorkingArea.Height-ClientSize.Height)
Remélem, ez különféle felbontások és méretezések esetén is megfelelően működik majd, de ezt csak próbálgatások után tudom megállapítani.[ Szerkesztve ]
-
Tomi_78
tag
És az miért van, hogy így számítom ki az értékeket:
kepernyomag=Screen.PrimaryScreen.Bounds.Height;
talcamag=kepernyomag-Screen.PrimaryScreen.WorkingArea.Height;
cimsormag=Screen.PrimaryScreen.WorkingArea.Height-ClientSize.Height;
és ha a MainFormPaint-ben a DrawString-gel kiíratom, akkor kb. 40-nel eltérnek az értékek egymástól, ha a DrawString-ben a fenti változók szerepelnek attól, mintha változók helyett a konkrét számítást tenném be, ToString()-gel a végén?
Tehát a DrawString(kepernyomag+"-"+talcamag...)
nem ugyanazt adja, mint a
DrawString(Screen.PrimaryScreen.Bounds.Height.ToString()...
stb. -
dqdb
nagyúr
válasz Tomi_78 #10062 üzenetére
Nem kell itt próbálkozni, ott van a
Screen.PrimaryScreen.WorkingArea
, azt kell beállítani az ablak pozíciójának, ha az első képernyőd akarod megjeleníteni, és ekkor a tálca nélküli teljes képernyőméretet kihasználod.A te megoldásod elvi szinten bukik el, mert az, hogy a tálca teteje, az esetek egy részében értelmezhető fogalom csak. A tálcát lehet balra, jobbra és felülre dokkolni, emellett el lehet rejteni automatikusan, több monitornál simán lehet, hogy csak az elsődleges monitoron van tálca, a többin nem, stb.
Screen.PrimaryScreen.WorkingArea.Height-(Screen.PrimaryScreen.WorkingArea.Height-ClientSize.Height)
Egyszerűsítsük kicsit a képletet:Screen.PrimaryScreen.WorkingArea.Height - (Screen.PrimaryScreen.WorkingArea.Height - ClientSize.Height) =
Screen.PrimaryScreen.WorkingArea.Height - Screen.PrimaryScreen.WorkingArea.Height + ClientSize.Height =
ClientSize.Height
Ez csak abban az esetben adja meg a tálca tetejének helyét, ha
1. a Windowsban a tálca alulra van beállítva
2. az ablak maximalizálva van
3. az ablaknál aFormBorderStyle = FormBorderStyle.None
van beállítva és nincsen menü[ Szerkesztve ]
tAm6DAHNIbRMzSEARWxtZW50ZW0gdmFka5RydIJ6bmkuDQoNClOBc4Ek
-
Tomi_78
tag
Értem már.
És arra van mód, hogy lekérdezzem a menüsor magasságméretét (ami most nálam 24 képpont, de ezt is az egér Y helyzetéből tudtam kikövetkeztetni)? Mert most a WorkingArea teteje (Top) 0-nál van, de mindig beleszámítja a fenti menüsort is, ami nekem nem kell.
Vagy csakis az a megoldás, hogy eltüntetek mindenféle menüsort aFormBorderStyle = FormBorderStyle.None
paranccsal? -
Tomi_78
tag
Még egy kérdés: ha egy 2d tömböt deklarálok, de később, más névtéren belül inicializálnám, azt hogyan kell megtenni? Mert ez most hibás; azt írja, hogy: "Itt azonosítónak kellene szerepelnie."
void MainFormLoad(object sender, EventArgs e)
{
int[,] palya;
switch (mostpalya) {
case 1:
palya[,] = {{0,0,0,0,0,0,0,0,0,0},//Ennél írja a hibát!
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{2,0,0,0,1,0,0,0,0,2},
};
break;
}}
-
Tomi_78
tag
válasz joysefke #10069 üzenetére
Sajnos nem, mert azt írja ki, hogy:
Inicializálatlan „palya” lokális változó használata (CS0165)Pedig egyszer már deklarálva van, csak éppen a switch() névtéren kívül, az előtt.
De nekem az kéne, hogy deklarálom egyszer a MainFormLoad() elején, és azon belül felhasználható legyen akármilyen belső szerkezetben. -
Alexios
veterán
válasz Tomi_78 #10070 üzenetére
másold be az egész releváns kódrészletet, pusztán hibaüzenetből nehéz látni mi a gond
De ennek így jónak kéne lennie:
int[,] palya;
switch (mostpalya) {
case 1:
palya = new int[,]{{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{2,0,0,0,1,0,0,0,0,2},
};
break;
}
[ Szerkesztve ]
-
dqdb
nagyúr
válasz Alexios #10071 üzenetére
A hibaüzenet alapján az lesz a probléma, hogy nem inicializálja minden kódúton a változót, és használná. Az
int[,] palya = null
megoldja a fordítási hibát, de az ellenőrzéseket persze bele kell tenni a kódba.[ Szerkesztve ]
tAm6DAHNIbRMzSEARWxtZW50ZW0gdmFka5RydIJ6bmkuDQoNClOBc4Ek
-
Tomi_78
tag
Tanácsaitok alapján végül így hibaüzenetek nélkül működni kezdett a programom:
int[,] palya = null;
switch (mostpalya) {
case 1:
palya = new int[,]{{0,0,0,0,0,0,0,0,0,0},
Akkor ezek szerint az első és legfőbb deklarálási helyen már értéket kell adni neki, még ha ez null is, illetve az utána következő, értékekkel történő feltöltés helyén használni kell a new int[,]-et? -
pmonitor
aktív tag
válasz Tomi_78 #10073 üzenetére
Csak azért írtam, hogy addig olvasgasd dqdb posztját, mert a posztodból egyértelműen látszik, hogy nem értetted meg.
ezek szerint az első és legfőbb deklarálási helyen már értéket kell adni neki, még ha ez null is,
Ez rossz konzekvencia. Ugyanis abban az esetben, ha minden kódúton inicializálod a változót, akkor nem kell még null-t sem adni a deklarálás helyén. Tehát ez is jó:
int[,] palya;
switch (mostpalya)
{
case 1:
palya = new int[,] {{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{2,0,0,0,1,0,0,0,0,2},
};
break;
default:
palya = new int[,] {{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{2,0,0,0,1,0,0,0,0,2},
};
break;
}Itt a default ág miatt mindenképpen inicializálva van annak ellenére, hogy deklaráláskor nem adtam neki null-t.
http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
Tomi_78
tag
Hát igen, furcsa egy kicsit nekem a változókezelés, de azért csak kapisgálom, hogy C#-ban a blokkon vagy névtéren belül létrehozott változók csak ott érvényesek.
De pl. az miért van, hogy ha megadok egy változót és ugyanazt if feltétel elágazásaiban használnám fel, akkor rendellenesen viselkedik tőle a programom?
Akkor ezt így nem lehet?
int valtozo;
if (...) {
valtozo = ...;
(...)
}
(... még pár ugyanilyen if ág ...)
if (...) {
valtozo = ...;
(...)
}
Tehát minden ághoz külön változónevet adjak meg? Ez kissé pazarlónak tűnik a változónevekkel.
És ugyanezt tapasztaltam switch elágazásnál is:
var valtozo;
switch (...) {
case 0: valtozo = ...;
break;
case 1: valtozo = ...;
break;
}
Hibaüzenet ez utóbbinál: Az implicit típusmeghatározású lokális változókat inicializálni kell. -
Alexios
veterán
válasz Tomi_78 #10076 üzenetére
Fordítsuk meg a kérdést és gondold át mit kéne csináljon a program akkor ha olyan ágba kerülsz ahol nem inicializálod majd később hivatkozol rá. Vagy adsz egy default értéket (pl az if/switch blokkok előtt, int valtozo =1; ), vagy minden lehetséges úton inicializálni kell ha később hivatkozol rá.
Az utóbbinál amúgy az a baja hogy ha var-t használsz akkor egyből inicializálni kell, mert a compiler nem tudja hogy mi az. A switchen belül pl az egyik ágban számot, másikban szöveget adnál neki, honnan tudja melyik a helyes? Ez egy erősen típusos nyelv, nem lehet egy változó egyszerre több típus, tehát vagy megmondod az elején hogy milyen típus lesz és később is tudod inicializálni, vagy használod a var kulcsszot és egyből értéket adsz neki hogy tudja milyen típus kell legyen.
[ Szerkesztve ]
-
joysefke
veterán
válasz Tomi_78 #10078 üzenetére
Valami alapozó könyvet kellene olvasnod, hogy helyére kerüljenek a dolgok.
A "new" utasítással példányosítottál egy osztályt, az objektum a (heap) memóriában jött létre, a var kulcsszóval deklarált változód a stacken van (a futó metódus scopeján belül) ez a változó egy referencia ami a heapen lévő objektumra mutat. A referencián keresztül tudod elérni és használni a heapen lévő objektumodat.A var -ral deklarált változód típusa már kódszerkesztési időben ismert a fejlesztőkörnyezet számára. Ha a fejlesztőkörnyezet nem tudja a típust eldönteni, akkor be fogja azt a kódrészt pirosítani.
A var csak arra van, hogy neked kényelmesebb legyen, ne kelljen a hosszú típusnevet kiírni, illetve refaktorálásnál is előnyös lehet.var myObject = new MyClass(); esetén a myObject típusa "MyClass típusú referencia";
-
pmonitor
aktív tag
válasz joysefke #10079 üzenetére
a var kulcsszóval deklarált változód a stacken van (a futó metódus scopeján belül) ez a változó egy referencia ami a heapen lévő objektumra mutat.
Kösz, hogy leírtad azt, amit már ~12 éve írogatok: hogy az int-nek nem őse az object. Object NEM lehet a veremben(ott csak a referenciája lehet(a stack meg csak az érték típusok memóriája.
Legalább van 1 valaki, aki ezt írja. Jól esik!
Egyébként tudod, hogy melyik alapozó könyvben vannak leírva így részletezve ezek a dolgok? Mert én ilyent sajnos nem tudok. Mert én a legjobb ms vs c# könyvnek ezt tartom.. De még abban sincsenek ezek ilyen részletességgel leírva. Ezért is zártak ki 3 topikból is, mert én le mertem írni az igazat... Ők meg könyvben nem olvasták.http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
Alexios
veterán
válasz pmonitor #10080 üzenetére
Biztos ezért zártak ki
Már linkeltem amúgy neked a hivatalos language specet persze leírtad hogy ők sem tudják miről van szó [link] All struct types implicitly inherit from the classSystem.ValueType
, which, in turn, inherits from classobject
.
Tudom hogy úgysem hiszed el, de azért futtasd le ezt a kódot is és nézd meg az outputot, gondolom a nyelv maga se tudja miről beszél:int x = 1;
Console.WriteLine(x is object);
-
pmonitor
aktív tag
válasz fatal` #10082 üzenetére
Ha az object az őse(rá gondolni is rossz tegyük fel), akkor miért van szükség boxing-ra???
Object -> Objet relációban mi értelme van a boxingnak?
Sztem a válasz nagy egyszerű: azért szükséges a boxing, mert az érték típusok különböznek az object től. Csak valahogyan "szinkronba" kellett hozni az érték típusokat az Object-el. Erre találták ki lényegében a boxing-ot. Ami azt hivatott szolgálni, hogy létrehoznak 1 vadi új Object-et a hap-ben, és annak a mezője az érték típus. Gyakorlatilag az érték típusokon a műveletek(metódusok) nem is érték típusokkal dolgoznak, hanem a boxingolt típussal. Pl. a Console.WriteLine() is ígys csinálja, Az is is ezt használja stb...[ Szerkesztve ]
http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
pmonitor
aktív tag
válasz pmonitor #10083 üzenetére
Ha jól emléxem, akkor már többször linkeltem be ezt a linket. Ez a másik fórumról való. Ott oldottam meg. Maga a kód(ami nem működik:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GenericTest
{
interface ITorol
{
void delete();
}
class GenerikusTipus<T>
{
T adat;
public GenerikusTipus(T adat)
{
this.adat = adat;
}
public T GetErtek()
{
return adat;
}
public void TorlunkHaTudja()
{
if (adat is ITorol)
(adat as ITorol).delete();
}
}
struct Valami : ITorol
{
public int ertek;
public Valami(int ertek)
{
this.ertek = ertek;
}
public void delete()
{
ertek = 0;
}
new public string ToString()
{
return ertek.ToString();
}
}
class Program
{
static void Main(string[] args)
{
Valami v = new Valami(5);
GenerikusTipus<Valami> genTip = new GenerikusTipus<Valami>(v);
Console.WriteLine(genTip.GetErtek().ToString());
genTip.TorlunkHaTudja();
Console.WriteLine(genTip.GetErtek().ToString());
Console.ReadKey();
}
}
}A "megoldásom":
Az as operátor ugye csak referencia, ill. nullabe típusok esetén működik. Tehát akkor az adott típust ki kell tenni object-be(ami ugyebár referencia típus), ez már magában hordozza a "metaadatokat" is. Na most így már alkalmazhatónak kell lennie az object példányra az as operátornak. Viszont a végén az adat-ba be kell tenni a kapott értéket.
if (adat is ITorol)
{
object o = adat;
(o as ITorol).delete();
adat = (T)o;
}Ez érdekességnek jó, de "élesben" nem igazán használnám...
Ha ezt a kódot(és a megoldást) valaki becsülettel megnézi, akkor egyértelműen látszik, hogy a metódusok 1 boxingolt típussal(másolattal) dolgoznak. Ezért van az, hogy az o objectet a törlés után vissza kell tenni az aktuális mezőbe. Az érték típusok csak az alapműveletek esetén(*/+-) nagyon gyorsak. metódushívás esetén nagyon lassú.
http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
Alexios
veterán
válasz pmonitor #10083 üzenetére
A fő probléma azzal van hogy a referencia típus fogalmát kevered az object-el.
Pusztán az hogy az értéktípusok is az object-ből származnak végső soron(nem nehéz amúgy ezt belátni, nem véletlen ignoráltad gondolom a kód példámat is, de ugyanúgy elérhető minden metódus egy int-en is ami egy objectben van, csak hogy még szemléletesebb legyen, ha már a language specet teljesen ignorálod), nem jelenti azt hogy ettől a heap-ben vannak tárolva. Pont ez a System.ValueType lényege, ennek köszönhetően vannak értéktípusként kezelve. Tehát az hogy a System.ValueType-ból származik, nem jelenti hogy ez egy referencia típus, hiszen pont a System.ValueType miatt lesz értéktípus, de ettől az még az objectből származik. Ha pl. egy intet objectként kezelsz akkor jön a boxing, hiszen referencia típusként akarod kezelni(itt is látszik hogy az object az ősosztályuk amúgy, hiszen simán átadhatsz egy intet mondjuk egy metódusnak ami objectet vár, mindenféle compiler error).
Kicsit olyan ez inkább mintha egy ősosztályán át hivatkoznál egy példányra, ott sem érheted el a metódus/propertyk stb amik a leszármazott osztályban vannak, érték típusoknál meg ha objectként hivatkozol rá akkor jön a boxing, és "elveszted" a leszármazott érték típus tulajdonságokat.(ez csak egy analógia, nem a pontos mechanizmus a kötekvést elkerülendő)[ Szerkesztve ]
-
joysefke
veterán
válasz Alexios #10086 üzenetére
Magyarázhatsz neki. Ha elolvas valamit, azt nem azért teszi, hogy a hasznos tudását növelje, hanem muníciót gyűjt a következő hónapok kötekedéséhez, ahol a "profi programozókat" (az ő szava járása) szapulja akik valami fontosnak vélt dolgot nem jól tudnak.
Ha az elmúlt éveket nem trollkodással töltötte volna, akkor akár "profi programozó" programozó is lehetne ami nyilván mindig is lenni akart. -
pmonitor
aktív tag
válasz Alexios #10081 üzenetére
futtasd le ezt a kódot is és nézd meg az outputot, gondolom a nyelv maga se tudja miről beszél:
int x = 1;
Console.WriteLine(x is object);
Ez valami vicc? Megnézted, hogy mire fordul? Megmutatom:bool b;
int x = 0x11;
b = x is int;
ugyanez ASM-ben:05465EF5 mov dword ptr [ebp-3Ch],1
ezt mégegyszer kiemelem:mov dword ptr [ebp-3Ch],1
Ezzel fordítási időben(ha létezik a változó), akkor azt mondja:
Ha valaki megkérdezi, hogy 1 változó Object-e, akkor 1szerűen mond azt, hogy igen. Tehát már fordítási időben "beleégeti a kódba", hogy true-t adjon vissza. Ez ugyanaz, mintha ezt írnád:bool b = true;
object obj = b;
Console.WriteLine("{0}", obj);De ez is ugyanarra fordul:
bool b = true;
08455EEE mov dword ptr [ebp-3Ch],1
int x = 1;
Ezek az MS-es fiúk nagyon rafkósak ám!! Bármiféle ellenőrzés nélkül kiíratják, hogy true!! Ilyen "csalással" könnyű azt mondani, hogy minden object...
Na de nézzük meg, hogy mi is történik akkor, amikor 1 érték típust beleteszünk egy objectbe:bool b = true;
int x = 0x55;
object obj = x;
object obj2 = x as object;
Console.WriteLine("{0} {1}", obj, obj2);Ez a következőre fodul:
int x = 0x55;
05175F21 mov dword ptr [ebp-3Ch],55h
object obj = x;
05175F28 mov ecx,4E0C8D0h
05175F2D call CORINFO_HELP_NEWSFAST (0300300Ch)
05175F32 mov dword ptr [ebp-48h],eax
05175F35 mov ecx,dword ptr [ebp-48h]
05175F38 mov eax,dword ptr [ebp-3Ch]
05175F3B mov dword ptr [ecx+4],eax
05175F3E mov ecx,dword ptr [ebp-48h]
05175F41 mov dword ptr [ebp-40h],ecx
object obj2 = x as object;
05175F44 mov ecx,4E0C8D0h
05175F49 call CORINFO_HELP_NEWSFAST (0300300Ch)
05175F4E mov dword ptr [ebp-4Ch],eax
05175F51 mov edx,dword ptr [ebp-4Ch]
05175F54 mov ecx,dword ptr [ebp-3Ch]
05175F57 mov dword ptr [edx+4],ecx
05175F5A mov edx,dword ptr [ebp-4Ch]
05175F5D mov dword ptr [ebp-44h],edx
Console.WriteLine("{0} {1}", obj, obj2);Ebből ezeket a sorokat emelném ki:
05175F2D call CORINFO_HELP_NEWSFAST (0300300Ch)
05175F49 call CORINFO_HELP_NEWSFAST (0300300Ch)
Ezekben a sorokban látszik, hogy 1 új object jön létre. Boxing történt. De ezek már nem érték típusok, hanem obj-ba és obj2-be bedobozolt int-ek. Ezek már referencia típusok, amiknek a mezőjében int van. És természetes, hogy vmi érték típust dobozolnak be 1 referencia típusba(obj, obj2), akkor az már referencia típus. Ha ellenőrizné is a program, hogy tényleg object-e az ősük, akkor is nyilván true-t adna vissza, hiszen ezek object-ek. Az más kérdés, hogy azért object-ek, mert bedobozolták őket. Ezt bizonyítja a következő kód is:05175F3B mov dword ptr [ecx+4],eax
Itt az ecx regiszterben van a típus azonosító(nevezhetjük object-nek), de az értéket[ecx+4]
-be teszi bele(itt is látszik, hogy ez már referencia típus, mert eax értékét nem az dword ptr [ecx]-be teszi, hanem az object címét kihagyva az [ecx+4]-be. Ez is azt igazolja, hogy ez már referencia típus.http://www.bferi.hu/download.php ; http://bferi.hu/egyeb.php
-
Tomi_78
tag
Na, ez vajon miért van?
Van egy saját osztály a programomban, a JatekElemei. Ebben egy public byte típusú, id nevű változó.
Aztán adott egy idk nevű, 0 kezdőértékű globális változó a program elején:
public partial class MainForm : Form
{
byte idk=0;És amikor létrehozom a JatekElemei egy példányát:
var egyarc = new JatekElemei();
(...)
egyarc.id=idk+1;
idk+=1;a következő hibaüzenet "örvendeztet meg" az egyarc.id=idk+1; sorral kapcsolatban:
"A(z) „int” típus nem konvertálható implicit módon „byte” típusra. Van explicit konverzió (esetleg hiányzik egy típuskonverzió). (CS0266)"Kérdésem: hol van itt az int típus, mikor mindkettőt byte-ként adtam meg?
-
Tomi_78
tag
válasz joysefke #10090 üzenetére
S valóban. Hát, erre bizony nem gondoltam volna sosem, hogy egy konkrét szám maga is lehet valamilyen típusú. De köszönöm szépen a segítséget; az int típusra állítás tényleg megoldotta.
Amúgy csupán memóriatakarékossági okból lett volna szükségem a byte típusra, mert az id és idk nem lett volna több a programban, mint 255. -
joysefke
veterán
válasz Tomi_78 #10091 üzenetére
Amúgy csupán memóriatakarékossági okból lett volna szükségem a byte típusra, mert az id és idk nem lett volna több a programban, mint 255.
Ezért mondtam, hogy érdemes lenne valami alapozó könyvet olvasgatni. Egyébként addig nincs értelme optimalizálgatni, amíg arra nincs szükség (, illetve amíg nem tudod mit csinálsz).
A programodban biztos lehetsz benne, hogy az hogy a MainForm ban egy fieldnek bool-t használsz int helyett semmi jelentősége nincsen illetve egyetlen byte-ot sem spórolsz, a MainForm byte-re pontosan ugyanakkora lesz.
Ennek az oka, hogy az objektumok fieldjei a memóriában nem feltétlenül teljesen folytonosan helyzkednek el, hanem igazítva vannak.class MyClass
{
byte B;
int Num;
}Ez például jó eséllyel a "Num" 4byteos mérete miatt 4 bytejával lesz igazítva, tehát a B is 4 byteot fog elfoglalni jó eséllyel. (futtatókörnyezet függő). Az 1byte hasznos terület után lesz 3byte foghíj. Sebességben sincsen semmi különbség két byte összeadása illetve két integer összeadása között. (Nem mintha ez bármit számítana)
De ezekkel egyelőre nincs értelme foglalkoznod.
[ Szerkesztve ]
-
Keem1
addikt
Srácok, szeretnék helpet kérni.
ASP.Net Core Razor. Van két Oauth authentication-öm: Google, Spotify.
Van a Spotify pagemoldelen belül egy OnGetAccount(), amit értelemszerűen ha a Spoti login ok, akkor jelenjen meg. Nem logged off, nem Google logged in, hanem csakis ha Spoti logged in.
Hogy tudom rávenni a /Spotify/Account oldalt, hogy ha logged in akkor OK, amúgy /Spotify/Login redirect?Valami ilyesmit találtam a metódus fejhez:
[Authenticate]De ez hatástalan, semmi nem történik.
Előre is köszi.
Új hozzászólás Aktív témák
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Nem tudom a dal címét, előadóját
- AMD GPU-k jövője - amit tudni vélünk
- Battlefield 2042
- Egyre több piacra eljut az eredetileg korlátozott Ryzen 5 7600X3D
- iPhone topik
- Samsung Galaxy S23 Ultra - non plus ultra
- Lakáshitel, lakásvásárlás
- Okosóra és okoskiegészítő topik
- Rezsicsökkentés, spórolás (fűtés, szigetelés, stb.)
- Megszűnik az első két Ryzen generáció támogatása a Ryzen Masterben
- További aktív témák...
Állásajánlatok
Cég: Ozeki Kft
Város: Debrecen