Keresés

Új hozzászólás Aktív témák

  • Alexios

    veterán

    válasz pmonitor #10132 üzenetére

    Pontosan ilyeneket ir, nem véletlen vagy kitiltva a fő progos topikból, valószinűleg itt is azt kéne.

  • petyus_

    senior tag

    válasz pmonitor #10127 üzenetére

    nem hiszem, hogy programnyelvként írta martonx, .net fejlesztő, aki főleg asp.net framework-öt használ

  • sztanozs

    veterán

    válasz pmonitor #10106 üzenetére

    A rosetta miert nem jo, ott van c is implementalva amit kerestel...

  • martonx

    veterán

    válasz pmonitor #10096 üzenetére

    fontos, hogy nagybetűvel írtam a Usert, ugyanis Asp.Net-ben így hívják a user entitást, ami HttpContext-ben van. Szóval reményeim szerint érti, mire gondolok. Ez éppen egy nagyon jó példa arra, hogy még Asp.Net-en belül is annyiféle megoldás van, annyira szerteágazó, hogy rohadtul nem az a kérdés, hogy a byte array hány byte-on tárolódik, hanem lásd a fenti kérdést.
    Amire még én, mint Asp.Net fejlesztő se tudok csukott szemmel válaszolni, mert razort pl. sose használtam, MVC-t, és API-t szoktam fejleszteni. Nyilván fingom sincs fejből, hogy mi lehet az OnGetAccount-ban, mire lát rá, mit kellene pluszban behúzni ahhoz, hogy megjelenjen a User.
    Meg persze kód példa nélkül nehéz is konkrétumokról beszélni :D Meg persze, ha rászánnék még plusz 20 percet, és életemben először nyitnék egy razor page-es Asp.Net-es projektet, akkor valószínűleg pontosabban tudnék válaszolni neki, így csak iránymutatást tudok adni.

  • 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ő)

  • 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ú.

  • fatal`

    titán

    válasz pmonitor #10080 üzenetére

    Az összes struct a System.ValueTypeból származik, aminek az őse az object.

  • Alexios

    veterán

    válasz pmonitor #10080 üzenetére

    Biztos ezért zártak ki :D
    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 class System.ValueType, which, in turn, inherits from class object.
    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);

  • Alexios

    veterán

    válasz pmonitor #10049 üzenetére

    Akkor még egyszer utoljára leírom.

    Az állítás nem az volt hogy mindegy melyiket használod _bármelyik_ esetben, hanem hogy _ebben_ az esetben mindegy volt, hiszen ezek ciklusok, nem típusokon lehet végigmenni velük, hanem gyűjteményeken. Az eredeti kérdező kérdése az volt hogy mire jó a foreach, továbbra is fenntartom, hogy az ő esetében az lett volna a lényeg hogy gyűjteményt csináljnon és menjen rajta végig(ahogy végülis meg is csinálta), ezt pedig bármivel megcsinálhatta, foreach/for/while _ebben_ az esetben mindegy, hiszen a gond nem a foreach-el magával volt hanem hogy amit ő szeretett volna abban a formában nem lehet.
    Azt hogy mit lehet módosítani közben, vagy törölni, csak te hoztad ide, senki más nem vitatta, hiszen az állítás nem az volt hogy foreachben az aktuális itemet nem lehet megváltoztatni, hanem hogy az hogy pl. foreach(string a string) miért nem értelmes.

    while() és a for() egyébként csak megerőszakolva működik minden enumeratoron(de nyilván nem erre tervezték.
    Ez egy teljesen mellékszál, de ez nem megerőszakolás, és annyira erre tervezték hogy a foreach egy syntactic sugar ahogy fatal is írta, azaz valójában build után ez while-al fog menni az enumeratoron. Ettől függetlenül te, én, stb, mint végfelhasználó nem így fogjuk írni, hiszen nyilván azért hozták létre a syntactic sugar-t hogy használjuk, de ettől még nem árt tisztában lenni a működésével, és azzal hogy ez nem megerőszakolás.
    Illetve a mindegy nem mindegy részhez annyit, hogy _mindent_ amit foreach-el meg lehet írni, meg lehet for vagy while ciklussal(hiszen a foreach is egy fancy while ciklus), de fordítva ez már nem igaz, szóval fölösleges újabb példákat hozni rá, mert senki nem vitatja ezt.

    +1 a linkedről:
    c#-ban mindennek van egy közös szülőtípusa, úgy hívják object
    Most ha attól eltekintünk hogy tök nyilvánvaló kötekvés ha azt nézzük az eredeti kérdező kérdésének mi volt a lényege, ha jól értem erre a cáfolatod a struct akar lenni [link] itt a hivatalos msdn c# language spec doksi, ez egyértelműen írja hogy All struct types implicitly inherit from the class System.ValueType, which, in turn, inherits from class object
    Tehát minden struct implicit a System.ValueType-ból származik, az pedig az objectből. Ettől még nyilván van lényegi különbség a value és reference típusok között, nem kell cáfolaltot felhozni, ha ez nem tetszik a Microsoft-al vitatkozz, ők tervezték a nyelvet, és ez az ő reference dokumentumuk.

  • fatal`

    titán

    válasz pmonitor #10045 üzenetére

    Hogy jön ide a módosítás? Senki nem beszélt erről.

    Egyébként az objektumok módosíthatóak, a referenciájuk iteráció közben nyilván nem.

    A foreach egyébként pont egy syntactic sugar az enumeratoron.

  • Alexios

    veterán

    válasz pmonitor #10043 üzenetére

    Nincs olyan amin foreach-el végig lehet menni, de while-al nem, fentebb mutattam is példát miért van ez így(mert pl. a foreach is egy while-ra fordul), a hashset sem kivétel ezalól(for-al is meg lehet természetesen csinálni, nem muszáj indexel elérni elemeket for cikluson belül is, mégha nem is célszerű). Az más kérdés persze megint, hogy magaddal vitatkozol.

  • pmonitor

    aktív tag

    válasz pmonitor #10041 üzenetére

    Arról nem is beszélve, hogy a for és a while nem is mindenre használható. Pl. HashSet<TesztOsztaly> - on nem.

    Semmiképp nem összehasonlítható!

  • Alexios

    veterán

    válasz pmonitor #10039 üzenetére

    Nézd már meg az eredeti kérdést, nem volt benne .Count, pont erről beszéltem hogy az nem egy gyűjtemény, hanem egy típus. A JatekElemei nem egy lista, tömb, akármi más volt, hanem egy osztály típus, max statikus countja lehetne technikailag, ami nincs. Ahogy ez is volt a kérdés hogy miért nem lehet végig menni foreachel rajta, és azért mert nem egy gyűjtemény. Ugyanúgy for és while-al se lehet vegigmenni rajta, mert nem egy gyűjtemény, de még csak nem is egy peldanyositott akármi

  • Alexios

    veterán

    válasz pmonitor #10037 üzenetére

    De tökmindegy, hiszen arról volt szó hogy az esetben _mindegy_ melyikkel iterálna végig rajta, egy gyűjteményen(vagy enumeratoron, mielőtt ebbe köt valaki) kell és nem egy típuson. Ebből a szempontból teljsen mindegy hogy for, while, foreach, mert a kérdés nem ez volt, hanem az hogy lehetséges-e ilyen:
    foreach(tipus objnev tipus){}
    ami ugye nem. Ilyen szempontból tökmindegy, mert ilyet sem lehet hogy while(tipus) meg olyat sem hogy for(tipus), mert értelmezhetetlen ebbe a formában, hiszen ez nem egy gyűjtemény. Az állítás nem az volt hogy mindig mindegy melyiket használod, hanem ebben az esetben az.

  • Alexios

    veterán

    válasz pmonitor #10035 üzenetére

    Ha el is olvasod az egész mondatot amit írtam beszéljünk.
    Ha már nagyon kötekvés akkor meg lehet nézni mit is csinál egy foreach:
    int number;
    while (enumerator.MoveNext())   {     number = enumerator.Current;   }

    Innen tök érthető hogy miért nem lehet megváltoztatni, csak hát sosem mondtam hogy meg lehet, sőt, teljesen másról beszéltem.

  • Alexios

    veterán

    válasz pmonitor #10032 üzenetére

    Nem tudom ennél érthetőbben leírni, sajnálom ha csak pár szavas kiragadásig sikerül eljutni, olvasd tovább a mondatot is, sőt azt is leírtam futólag hogy miért nem lehet módosítani a gyűjteményt később.

  • Alexios

    veterán

    válasz pmonitor #10030 üzenetére

    Most nem teljesen értem ebből a szempontból a kötekvést, be lehet hozni persze értéktípusokat, akkor 98%-ban minden az objectből jön, a lényeg hogy nem kell csinálni egy őstípust csak azért hogy legyen egy őstípus.

    Nem tök mind1. Mert pl. foreach esetén nem módosíthatod magát az objektumot. Csak az objektum.akármi-t.
    Ezt pláne nem értem, ha az egész mondatot olvasod és nem csak a részét kiragadva, akkor úgy folytatódik hogy mindegy mert gyűjteményeken mennek végig. Persze most bele lehet menni iterátorokba, stb, meg abba hogy ez se teljesen igaz így, hiszen ha valami yield return-el adja a cuccokat az biztos gyűjtemény-e, de emberünk nem tudja min lehet egy ciklussal végigmenni, nem gondolnám hogy ez itt releváns.

    Mert pl. foreach esetén nem módosíthatod magát az objektumot. Csak az objektum.akármi-t.
    Ha már ennyire kötekedni akarunk, a gyűjteményt nem tudod módosítani, pont azért mert egy enumerátoron megy a foreach

  • pmonitor

    aktív tag

    válasz pmonitor #9542 üzenetére

    A következő módosítással sikerült megoldanom. Ezt:
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct PARTITION_INFORMATION_GPT
    {
    public Guid PartitionType;
    public Guid PartitionId;
    [MarshalAs(UnmanagedType.U8)]
    public EFIPartitionAttributes Attributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 36)]
    public string Name;
    }

    Így módosítottam:
    [StructLayout(LayoutKind.Sequential)]
    public unsafe struct PARTITION_INFORMATION_GPT
    {
    public Guid PartitionType;
    public Guid PartitionId;
    public EFIPartitionAttributes Attributes;
    public fixed byte Data[72];
    }

    Így kell az unsafe kód engedélyezése, de a probléma megoldódott.

  • leslie23

    tag

    válasz pmonitor #9526 üzenetére

    Nagyon köszi nektek a segítséget, még nem volt időm foglalkozni vele. :(
    Az asnyc-await biztos, az enabled propertyt elegendő lenne a menustripen false-ra tenni, szóval ez elegánsan hangzik. :) Az egyetlen félelmem továbbra is a színes ikonok miatti 2-3 másodperces szürke/színes "villogás", ami az enabled változtatása során történik. Ki fogom próbálni, ha nagyon zavaró, akkor marad az OnClick eventek programozott hozzáadása/lecsatolása.
    Köszi szépen a tippeket!

  • martonx

    veterán

    válasz pmonitor #9506 üzenetére

    Továbbra sem értek egyet. Kezdőkről, sőt ha az eredeti kérdést olvastad, ultrakezdőkről beszélünk.
    Akik nem azért kotorásznak a designer.cs file-ban, mert tudatosan abban akarnak módosítani, hanem mert olyan szinten fingjuk sincs, hogy mit csinálnak, hogy találomra bökdösnek a boldogan megtalált .cs file-okra.

    Ergo őket nem félrevezetni kellene, meg összezavarni, és ne abból indulj ki, hogy minden kezdő egyébként istenadta programozózseni, csak még kevés a tapasztalata.
    Hanem egyértelmű iránymutatásokkal terelgetni, és majd ha egyszer (valaha?) oda jut, hogy valamit elrontott a designer file-ok piszkálása nélkül, akkor jöhet az igazság minden részletének kibontása :D , hogy figyi vannak ezek a designer file-ok, amikről eddig azt mondtuk, hogy ezeket nem kellene piszkálni. No, de ezek nem poénból vannak ott, van olyan eset, amikor ezekben kell javítani a visual kódszerkesztő dolgait. Ilyenkor ezekbe tudatosan bele lehet, sőt kell is nyúlni.
    Ettől még az ökölszabály, hogy ezeket nem kellene piszkálni, továbbra is áll.

    Egyébként meg kötözködés helyett, neked is szabad megválaszolnod kérdéseket, szabad a pálya. :R Mindenki szabadidejében teszi, te is nyugodtan beleállhatsz, csak ne zavard össze, ne vidd félre szegény kezdőket :D

  • fatal`

    titán

    válasz pmonitor #9502 üzenetére

    Ismét terelsz. :) Nem azt mondtam, hogy nem javítunk meg elcseszett designer fájlokat, hanem, hogy nem gányolunk bele mindenfélét. Nyilvánvalóan nem árt, ha értjük, hogy mi van benne, de azt nem azt jelenti, hogy össze-vissza gányolunk benne.

    #9503: A fenti eset nem ritka, így ebben az esetben nem értek egyet, de nem ez volt a kiindulópont. :)

    De mindegy, túl sok hsz-t pazaroltunk erre, a lényeg, hogy alapvetően nem abban turkálunk.

  • Alexios

    veterán

    válasz pmonitor #9502 üzenetére

    De a kiindulási pont nem az volt, hogy miután elrontottunk valamit turkálni kéne benne, hanem hogy ha pl. új controlokat akar létrehozni, vagy meglevőkhöz hozzáadni, stb, akkor azt ne itt tegye.

    (A felvázolt problémádnál pedig egyszerűbb megoldás szeirntem ha visszacsinálod a módosításokat, mint ennyire belemélyedni ebbe :) vagy legalábbis 1. pont után érdemes lehet bekomitolni a változásokat, és nem érhet gond )

  • fatal`

    titán

    válasz pmonitor #9500 üzenetére

    Akkor most olvasd el mégegyszer a kiindulást adó kérdést/problémát.

    A designer által generált fájlba nem írunk bele. Erre jössz azzal, hogy nincs rá feltétlenül szükség. Senki nem is mondta, hogy van, lehet bármekkora kuplerájt csinálni a kódban, de nem erről volt szó.

  • fatal`

    titán

    válasz pmonitor #9498 üzenetére

    Igen, és? A designer semmit nem csinál, csak kódot generál. Nem azért nem írunk bele, mert az valami mágikus dolog lenne, hanem azért, mert, amikor legközelebb megnyitod a formot felül fogja írni.

  • pmonitor

    aktív tag

    válasz pmonitor #9497 üzenetére

    Talán 4 perc is volt... Ezért írtam, hogy tudni kell, hogy mit csinál az ember fia/lánya. :)
    using System;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Security.Permissions;

    [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public class Form1 : Form
    {
    private IContainer components;
    private WebBrowser webBrowser1;

    private MenuStrip menuStrip1;
    private ToolStripMenuItem fileToolStripMenuItem,
    saveAsToolStripMenuItem, printToolStripMenuItem,
    printPreviewToolStripMenuItem, exitToolStripMenuItem,
    pageSetupToolStripMenuItem, propertiesToolStripMenuItem;
    private ToolStripSeparator toolStripSeparator1, toolStripSeparator2;

    private ToolStrip toolStrip1, toolStrip2;
    private ToolStripTextBox toolStripTextBox1;
    private ToolStripButton goButton, backButton,
    forwardButton, stopButton, refreshButton,
    homeButton, searchButton, printButton;

    private StatusStrip statusStrip1;
    private ToolStripStatusLabel toolStripStatusLabel1;

    public Form1()
    {
    // Create the form layout. If you are using Visual Studio,
    // you can replace this code with code generated by the designer.
    InitializeComponent();

    // The following events are not visible in the designer, so
    // you must associate them with their event-handlers in code.
    webBrowser1.CanGoBackChanged +=
    new EventHandler(webBrowser1_CanGoBackChanged);
    webBrowser1.CanGoForwardChanged +=
    new EventHandler(webBrowser1_CanGoForwardChanged);
    webBrowser1.DocumentTitleChanged +=
    new EventHandler(webBrowser1_DocumentTitleChanged);
    webBrowser1.StatusTextChanged +=
    new EventHandler(webBrowser1_StatusTextChanged);

    // Load the user's home page.
    webBrowser1.GoHome();
    }

    // Displays the Save dialog box.
    private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
    {
    webBrowser1.ShowSaveAsDialog();
    }

    // Displays the Page Setup dialog box.
    private void pageSetupToolStripMenuItem_Click(object sender, EventArgs e)
    {
    webBrowser1.ShowPageSetupDialog();
    }

    // Displays the Print dialog box.
    private void printToolStripMenuItem_Click(object sender, EventArgs e)
    {
    webBrowser1.ShowPrintDialog();
    }

    // Displays the Print Preview dialog box.
    private void printPreviewToolStripMenuItem_Click(
    object sender, EventArgs e)
    {
    webBrowser1.ShowPrintPreviewDialog();
    }

    // Displays the Properties dialog box.
    private void propertiesToolStripMenuItem_Click(
    object sender, EventArgs e)
    {
    webBrowser1.ShowPropertiesDialog();
    }

    // Selects all the text in the text box when the user clicks it.
    private void toolStripTextBox1_Click(object sender, EventArgs e)
    {
    toolStripTextBox1.SelectAll();
    }

    // Navigates to the URL in the address box when
    // the ENTER key is pressed while the ToolStripTextBox has focus.
    private void toolStripTextBox1_KeyDown(object sender, KeyEventArgs e)
    {
    if (e.KeyCode == Keys.Enter)
    {
    Navigate(toolStripTextBox1.Text);
    }
    }

    // Navigates to the URL in the address box when
    // the Go button is clicked.
    private void goButton_Click(object sender, EventArgs e)
    {
    Navigate(toolStripTextBox1.Text);
    }

    // Navigates to the given URL if it is valid.
    private void Navigate(String address)
    {
    if (String.IsNullOrEmpty(address)) return;
    if (address.Equals("about:blank")) return;
    if (!address.StartsWith("http://") &&
    !address.StartsWith("https://"))
    {
    address = "http://" + address;
    }
    try
    {
    webBrowser1.Navigate(new Uri(address));
    }
    catch (System.UriFormatException)
    {
    return;
    }
    }

    // Updates the URL in TextBoxAddress upon navigation.
    private void webBrowser1_Navigated(object sender,
    WebBrowserNavigatedEventArgs e)
    {
    toolStripTextBox1.Text = webBrowser1.Url.ToString();
    }

    // Navigates webBrowser1 to the previous page in the history.
    private void backButton_Click(object sender, EventArgs e)
    {
    webBrowser1.GoBack();
    }

    // Disables the Back button at the beginning of the navigation history.
    private void webBrowser1_CanGoBackChanged(object sender, EventArgs e)
    {
    backButton.Enabled = webBrowser1.CanGoBack;
    }

    // Navigates webBrowser1 to the next page in history.
    private void forwardButton_Click(object sender, EventArgs e)
    {
    webBrowser1.GoForward();
    }

    // Disables the Forward button at the end of navigation history.
    private void webBrowser1_CanGoForwardChanged(object sender, EventArgs e)
    {
    forwardButton.Enabled = webBrowser1.CanGoForward;
    }

    // Halts the current navigation and any sounds or animations on
    // the page.
    private void stopButton_Click(object sender, EventArgs e)
    {
    webBrowser1.Stop();
    }

    // Reloads the current page.
    private void refreshButton_Click(object sender, EventArgs e)
    {
    // Skip refresh if about:blank is loaded to avoid removing
    // content specified by the DocumentText property.
    if (!webBrowser1.Url.Equals("about:blank"))
    {
    webBrowser1.Refresh();
    }
    }

    // Navigates webBrowser1 to the home page of the current user.
    private void homeButton_Click(object sender, EventArgs e)
    {
    webBrowser1.GoHome();
    }

    // Navigates webBrowser1 to the search page of the current user.
    private void searchButton_Click(object sender, EventArgs e)
    {
    webBrowser1.GoSearch();
    }

    // Prints the current document using the current print settings.
    private void printButton_Click(object sender, EventArgs e)
    {
    webBrowser1.Print();
    }

    // Updates the status bar with the current browser status text.
    private void webBrowser1_StatusTextChanged(object sender, EventArgs e)
    {
    toolStripStatusLabel1.Text = webBrowser1.StatusText;
    }

    // Updates the title bar with the current document title.
    private void webBrowser1_DocumentTitleChanged(object sender, EventArgs e)
    {
    this.Text = webBrowser1.DocumentTitle;
    }

    // Exits the application.
    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
    Application.Exit();
    }

    private void InitializeComponent()
    {
    this.components = new Container();
    this.webBrowser1 = new System.Windows.Forms.WebBrowser();
    this.menuStrip1 = new System.Windows.Forms.MenuStrip();
    this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
    this.pageSetupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.printToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.printPreviewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
    this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    this.toolStrip1 = new System.Windows.Forms.ToolStrip();
    this.goButton = new System.Windows.Forms.ToolStripButton();
    this.backButton = new System.Windows.Forms.ToolStripButton();
    this.forwardButton = new System.Windows.Forms.ToolStripButton();
    this.stopButton = new System.Windows.Forms.ToolStripButton();
    this.refreshButton = new System.Windows.Forms.ToolStripButton();
    this.homeButton = new System.Windows.Forms.ToolStripButton();
    this.searchButton = new System.Windows.Forms.ToolStripButton();
    this.printButton = new System.Windows.Forms.ToolStripButton();
    this.toolStrip2 = new System.Windows.Forms.ToolStrip();
    this.toolStripTextBox1 = new System.Windows.Forms.ToolStripTextBox();
    this.statusStrip1 = new System.Windows.Forms.StatusStrip();
    this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
    this.menuStrip1.SuspendLayout();
    this.toolStrip1.SuspendLayout();
    this.toolStrip2.SuspendLayout();
    this.statusStrip1.SuspendLayout();
    this.SuspendLayout();
    //
    // webBrowser1
    //
    this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
    this.webBrowser1.Location = new System.Drawing.Point(0, 74);
    this.webBrowser1.Name = "webBrowser1";
    this.webBrowser1.Size = new System.Drawing.Size(704, 304);
    this.webBrowser1.TabIndex = 0;
    this.webBrowser1.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.webBrowser1_Navigated);
    //
    // menuStrip1
    //
    this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    this.fileToolStripMenuItem});
    this.menuStrip1.Location = new System.Drawing.Point(0, 0);
    this.menuStrip1.Name = "menuStrip1";
    this.menuStrip1.Size = new System.Drawing.Size(704, 24);
    this.menuStrip1.TabIndex = 3;
    //
    // fileToolStripMenuItem
    //
    this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
    this.saveAsToolStripMenuItem,
    this.toolStripSeparator1,
    this.pageSetupToolStripMenuItem,
    this.printToolStripMenuItem,
    this.printPreviewToolStripMenuItem,
    this.toolStripSeparator2,
    this.propertiesToolStripMenuItem,
    this.exitToolStripMenuItem});
    this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
    this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
    this.fileToolStripMenuItem.Text = "&File";
    //
    // saveAsToolStripMenuItem
    //
    this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
    this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.saveAsToolStripMenuItem.Text = "Save &As...";
    this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click);
    //
    // toolStripSeparator1
    //
    this.toolStripSeparator1.Name = "toolStripSeparator1";
    this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6);
    //
    // pageSetupToolStripMenuItem
    //
    this.pageSetupToolStripMenuItem.Name = "pageSetupToolStripMenuItem";
    this.pageSetupToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.pageSetupToolStripMenuItem.Text = "Page Set&up...";
    this.pageSetupToolStripMenuItem.Click += new System.EventHandler(this.pageSetupToolStripMenuItem_Click);
    //
    // printToolStripMenuItem
    //
    this.printToolStripMenuItem.Name = "printToolStripMenuItem";
    this.printToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P)));
    this.printToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.printToolStripMenuItem.Text = "&Print...";
    this.printToolStripMenuItem.Click += new System.EventHandler(this.printToolStripMenuItem_Click);
    //
    // printPreviewToolStripMenuItem
    //
    this.printPreviewToolStripMenuItem.Name = "printPreviewToolStripMenuItem";
    this.printPreviewToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.printPreviewToolStripMenuItem.Text = "Print Pre&view...";
    this.printPreviewToolStripMenuItem.Click += new System.EventHandler(this.printPreviewToolStripMenuItem_Click);
    //
    // toolStripSeparator2
    //
    this.toolStripSeparator2.Name = "toolStripSeparator2";
    this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6);
    //
    // propertiesToolStripMenuItem
    //
    this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
    this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.propertiesToolStripMenuItem.Text = "Properties";
    this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.propertiesToolStripMenuItem_Click);
    //
    // exitToolStripMenuItem
    //
    this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
    this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
    this.exitToolStripMenuItem.Text = "E&xit";
    this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
    //
    // toolStrip1
    //
    this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    this.goButton,
    this.backButton,
    this.forwardButton,
    this.stopButton,
    this.refreshButton,
    this.homeButton,
    this.searchButton,
    this.printButton});
    this.toolStrip1.Location = new System.Drawing.Point(0, 24);
    this.toolStrip1.Name = "toolStrip1";
    this.toolStrip1.Size = new System.Drawing.Size(704, 25);
    this.toolStrip1.TabIndex = 2;
    //
    // goButton
    //
    this.goButton.Name = "goButton";
    this.goButton.Size = new System.Drawing.Size(26, 22);
    this.goButton.Text = "Go";
    this.goButton.Click += new System.EventHandler(this.goButton_Click);
    //
    // backButton
    //
    this.backButton.Enabled = false;
    this.backButton.Name = "backButton";
    this.backButton.Size = new System.Drawing.Size(36, 22);
    this.backButton.Text = "Back";
    this.backButton.Click += new System.EventHandler(this.backButton_Click);
    //
    // forwardButton
    //
    this.forwardButton.Enabled = false;
    this.forwardButton.Name = "forwardButton";
    this.forwardButton.Size = new System.Drawing.Size(54, 22);
    this.forwardButton.Text = "Forward";
    this.forwardButton.Click += new System.EventHandler(this.forwardButton_Click);
    //
    // stopButton
    //
    this.stopButton.Name = "stopButton";
    this.stopButton.Size = new System.Drawing.Size(35, 22);
    this.stopButton.Text = "Stop";
    this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
    //
    // refreshButton
    //
    this.refreshButton.Name = "refreshButton";
    this.refreshButton.Size = new System.Drawing.Size(50, 22);
    this.refreshButton.Text = "Refresh";
    this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
    //
    // homeButton
    //
    this.homeButton.Name = "homeButton";
    this.homeButton.Size = new System.Drawing.Size(44, 22);
    this.homeButton.Text = "Home";
    this.homeButton.Click += new System.EventHandler(this.homeButton_Click);
    //
    // searchButton
    //
    this.searchButton.Name = "searchButton";
    this.searchButton.Size = new System.Drawing.Size(46, 22);
    this.searchButton.Text = "Search";
    this.searchButton.Click += new System.EventHandler(this.searchButton_Click);
    //
    // printButton
    //
    this.printButton.Name = "printButton";
    this.printButton.Size = new System.Drawing.Size(36, 22);
    this.printButton.Text = "Print";
    this.printButton.Click += new System.EventHandler(this.printButton_Click);
    //
    // toolStrip2
    //
    this.toolStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    this.toolStripTextBox1});
    this.toolStrip2.Location = new System.Drawing.Point(0, 49);
    this.toolStrip2.Name = "toolStrip2";
    this.toolStrip2.Size = new System.Drawing.Size(704, 25);
    this.toolStrip2.TabIndex = 1;
    //
    // toolStripTextBox1
    //
    this.toolStripTextBox1.Font = new System.Drawing.Font("Segoe UI", 9F);
    this.toolStripTextBox1.Name = "toolStripTextBox1";
    this.toolStripTextBox1.Size = new System.Drawing.Size(250, 25);
    this.toolStripTextBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.toolStripTextBox1_KeyDown);
    this.toolStripTextBox1.Click += new System.EventHandler(this.toolStripTextBox1_Click);
    //
    // statusStrip1
    //
    this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    this.toolStripStatusLabel1});
    this.statusStrip1.Location = new System.Drawing.Point(0, 378);
    this.statusStrip1.Name = "statusStrip1";
    this.statusStrip1.Size = new System.Drawing.Size(704, 22);
    this.statusStrip1.TabIndex = 4;
    //
    // toolStripStatusLabel1
    //
    this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
    this.toolStripStatusLabel1.Size = new System.Drawing.Size(0, 17);
    //
    // Form1
    //
    this.ClientSize = new System.Drawing.Size(704, 400);
    this.Controls.Add(this.webBrowser1);
    this.Controls.Add(this.toolStrip2);
    this.Controls.Add(this.toolStrip1);
    this.Controls.Add(this.statusStrip1);
    this.Controls.Add(this.menuStrip1);
    this.Name = "Form1";
    this.menuStrip1.ResumeLayout(false);
    this.menuStrip1.PerformLayout();
    this.toolStrip1.ResumeLayout(false);
    this.toolStrip1.PerformLayout();
    this.toolStrip2.ResumeLayout(false);
    this.toolStrip2.PerformLayout();
    this.statusStrip1.ResumeLayout(false);
    this.statusStrip1.PerformLayout();
    this.ResumeLayout(false);
    this.PerformLayout();

    }


    protected override void Dispose(bool disposing)
    {
    if (disposing) { if (components != null) { components.Dispose(); } }
    base.Dispose(disposing);
    }
    }

  • fatal`

    titán

    válasz pmonitor #9495 üzenetére

    Kicsit kevered a dolgokat. Itt azért nincs külön designer fájl, mert kódból pakolja fel a controlokat a formra (nem is látszódnának a designerben VS alatt).

    Designer által létrehozott fájlokat nem piszkálunk, mert felül fog íródni (vagy épp elszáll a designer ha hülyeséget írnak bele). Persze át lehet írni őket, csak nagyon figyelni kell (viszont a példád nem állja meg a helyét).

  • joysefke

    veterán

    válasz pmonitor #9470 üzenetére

    1,
    bent maradt a hot pathban a Console.WriteLine() ==> így nem lehet tesztelni. Ha kiveszed sokszorosára gyorsul majd. (csak akkor ugye hol lesz az eredmény :D )

    2,
    Nem készítesz a bemeneti tömbről másolatot (ami nem feltétlenül baj) de ez azt jelenti hogy a bemeneti tömböt az első futás első iterációja elött egy rendezéssel már tönkreteszed. az algo aztán folyamatosan pörgeti a tömböt míg annak a rendezése át nem fordul (növekvőről csökkenőre)

    Kizárólag az algoritmus felépítésének köszönheted (és nem a benchmark felépítésének) hogy a tömb amin dolgozol hiába teszed tönkre az algo minden futásával újrarendeződik és így minden futás az első kivételével pontosan ugyanannyi lépést jelent. Az elsőben a qsort ideje különbözni fog a többi futás qsortjának idejétől (de ez elhamyagolható)

  • joysefke

    veterán

    válasz pmonitor #9467 üzenetére

    Hidd el hogy rossz az a benchmark amit csinálsz, de legalább konzekvensen az.

    C# kódot beilleszted?

  • joysefke

    veterán

    válasz pmonitor #9466 üzenetére

    Átírva C#-ba és használható formában
    A kezdeti 1x tömb-klónozáson kívül (hogy ne legyen elrontva a bemeneti tömb) teljesen allokációmentes.
    A char[] State tárolja az aktuális állapotot, a bool Next() pedig lépteti az és visszajelez a sikerről. Ha a char[] State állapotot nem csak olvasni akarod akkor értelemszerűen ki kell menteni róla egy másolatot.

    A char[] State köré lehetne még valami readonly wrappert rakni, de azt nem tudom hogy viselkedne.

    char[] megy bele ctor bemeneti paraméterként

    És ezen még lehetne gyorsítani. :)

    using System;
    namespace Permutator
    {
        class Program
        {
            static void Main(string[] args)
            {
                int i = 0;
                var p = new Permutator("abcdananana".ToCharArray());
                do
                {
                    i++;
                    Console.WriteLine(new string(p.State));
                }
                while (p.Next());
                Console.WriteLine($"Nr of results: {i}");
            }
        }
        public class Permutator
        {
            public char[] State { get; }
            int _size;
            bool isFinished = false;
            public Permutator(char[] symbols)
            {
                if (symbols?.Length > 0)
                {
                    _size = symbols.Length;
                    State = (char[])symbols.Clone();
                    Array.Sort(State);
                }
                else
                    throw new ArgumentException("input must be non-empty");
            }
            public bool Next()
            {
                // if we have already finished we indicate failure on getting next element
                // else we try to advance the state and propagate success of advancing state
                if (isFinished)
                    return false;

                isFinished  = !AdvanceState();
                return !isFinished;
            }
            bool AdvanceState()
            {
                // Find the rightmost character 
                // which is smaller than its next 
                // character. Let us call it 'first 
                // char' 
                int i;
                for (i = _size - 2; i >= 0; --i)
                    if (State[i] < State[i + 1])
                        break;
                // If there is no such character, all 
                // are sorted in decreasing order, 
                // means we just printed the last 
                // permutation and we are done. 
                if (i == -1)
                    return false;
                // Find the ceil of 'first char' 
                // in right of first character. 
                // Ceil of a character is the 
                // smallest character greater 
                // than it 
                int ceilIndex = findCeil(State, State[i], i + 1, _size - 1);
                char tmp = State[i];
                State[i] = State[ceilIndex];
                State[ceilIndex] = tmp;
                Array.Sort(State, i + 1, _size - i - 1);
                return true;
            }
            // This function finds the index of the 
            // smallest character which is greater 
            // than 'first' and is present in str[l..h] 
            int findCeil(char[] str, char first, int l, int h)
            {
                // initialize index of ceiling element 
                int ceilIndex = l;
                // Now iterate through rest of the 
                // elements and find the smallest 
                // character greater than 'first' 
                for (int i = l + 1; i <= h; i++)
                    if (str[i] > first && str[i] < str[ceilIndex])
                        ceilIndex = i;
                return ceilIndex;
            }
        }
    }

  • joysefke

    veterán

    válasz pmonitor #9461 üzenetére

    De ez az összes többi esetre is vonatkozik(teszt_1-teszt_5-ig). Nem állítom, hogy a teszt atompontos. De többször lefuttattam, és mindig hasonló eredményt adott az egymáshoz viszonyított idők tekintetében.

    A teszt mér valamit, de nem azt amire te kiváncsi vagy.

    Az optimalizálás 5letét az ismétléses permutáció algoritmusa adta. Ott nagyon sokat kell allokálni és feltölteni(bár a legjobb az lenne, ha csak feltölteni --tehát simán másolni-- kellene).

    Ha nem kell a mélységi bejárás során keletkező összes tömböt megtartani, csak mindig 1-1 újabbra van szükséged és tudod hogy egy tömbre mikor nem lesz már szükség, akkor érdemes lehet ezt kipróbálni. Ezzel ki tudod küszöbölni a heap allokációt. Én még nem használtam.

    ArrayPool<T> Class (System.Buffers) | Microsoft Docs

  • joysefke

    veterán

    válasz pmonitor #9458 üzenetére

    static unsafe void teszt_6(int[] source, int n)
            {
                int[] dest = new int[n];
                fixed (int* pSource = source, pdest = dest)
                {
                    int* pSource_0 = pSource;
                    int* pdest0 = pdest;
                    int* pmax = pSource_0 + n;
                    for (; pSource_0 < pmax; ++pSource_0, ++pdest0)
                    {
                        *pdest0 = *pSource_0;
                    }
                }
            }

    mivel a metódusnak visszatérési értéke nincsen (void), a program végeredménye szempontjából lényeges mellékhatás sincsen (nincsen IO, nem változtat semmilyen állapotot) ezért ezért honnan tudod, hogy futás közben release + optimalizáció beállítással ez egyáltalán lefut? (valószínűleg lefut, de nem kéne)

    Ráadásul a timert úgy indítod-állítod le, hogy a memóriamásoláson kívül szinte minden tesztesetedben van ciklikus heap allokáció is. Ha nagyot foglalsz a heapen akkor az triggerelhet egy GC futást is.

    Mivel a teszt-metódusaidat ciklusban futtatod, az iterációk között teleszemeteled a heapet halott objektumokkal ezért FOG futni a GC, többször, sokszor. A GC futás valószínűleg több időbe kerül mint maga a memóriamásolás. (pld mert a memóriaterületeket valamikor nullázni is kell stb) . Innentől kezdve a méréseid pontatlanok.

    Ha memóriát akarsz kézzel másolni, akkor #9455 szigorúan allokáció nélkül. az kimaxolja a mem sávszélt, az a másolás sebességének elméleti határa

    ====

    Az egészet arra éleztem ki, hogy a "fő programom"(a cutter) esetében sokat kell tömböt másolni. Igaz, hogy csak kis méretűeket.

    Csak másolni kell a tartalmat egyik helyről a másikra vagy allokálni kell és feltölteni? Elég jelentős a különbség. (nem ismerem a feladatot)

    ====

    A legnagyobb meglepetést azonban az Unsafe kód okozta. Kis méretű tömb esetén a "középmezőnyben" van. Nagy méretű tömb esetén azonban lényegesen a leggyorsabban végez az összes többinél.

    Két oka van:
    1,
    Az eredeti unsafe teszt-metódusodban nem volt for ciklusos heap allokáció hanem stackalloc volt => nincs GC a szemét eltakarítására, összehasonlíthatatlanul gyorsabb. Az összes többi teszt ahol new int[n] hívódik ciklikusan hatalmas handikeppel indult...
    2,
    Az unsafe kikapcsolja a tömb hozzáférések során az indexer értéktartomány ellenőrzését. ezzel csökkentetted a ciklusonkénti munkát (indexer értékhatár ellenőrzés + mem másolás helyett csak mem másolás). Gondolom a többi library metódus is unsafe-ként van belül megvalósítva. Csak ugye lsd 1. pont

  • pmonitor

    aktív tag

    válasz pmonitor #9458 üzenetére

    Az egészet arra éleztem ki, hogy a "fő programom"(a cutter) esetében sokat kell tömböt másolni. Igaz, hogy csak kis méretűeket. És ezt rekurzívan kell tenni(ismétléses permutáció generálásához). A Win api CopyMemory() esetén lényegesen gyorsabb lett az ismétléses permutáció generálása(a rekurzív hívásokban lévő tömb másolások gyorsulása miatt.) .

  • joysefke

    veterán

    válasz pmonitor #9456 üzenetére

    és az int [] dest nek mi lesz a sorsa miután kilépsz a metódusból?

  • joysefke

    veterán

    válasz pmonitor #9454 üzenetére

    Nem derül ki, hogy mit akarsz csinálni. És mi alapján választottad ki a bementő paramétereket.

    static unsafe void teszt_5(int[] source, int n)
    {
    fixed (int* pSource = source)
    {
    int* dest = stackalloc int[n];
    int* pSource_0 = pSource;
    int* pmax = pSource_0 + n;
    for (; pSource_0 < pmax; ++pSource_0, ++dest)
    {
    *dest = *pSource_0;
    }
    }
    }

    (1)
    bemegy egy tömb és egy int.

    (2)A stacken foglalsz egy int tömböt
    -ami nem tudja elhagyni a stacket
    -és nem lehet nagyobb mint a stack mérete (ráadásul a stackből foglalja a helyet aminek a metódus hívásakor már van egy a metódus számára ismeretlen mérete illetve a default stackméret futtatókörnyezettől is függ)

    (3)aztán feltöltöd az int[n] tömböt és
    (4)elfelejted

    Ha kézzel írnék tömbmásolásra egy UNSAFE metódust akkor bemenetként a már lefoglalt cél és forrástömb referenciáit vinném be aztán SIMD-del 32 byteonként másolnék (AVX register mérete).

    Amit te csinálsz ott egy int* pointert inkrementálsz és int méretben történik az adatmozgatás. (a mivel a ciklusok nem függenek az előzőektől ezért jó esetben 3-4 átlapolva történik meg)

    SIMD-del egyedül a memória sávszélessége szabna határt

  • cigam

    titán

    LOGOUT blog

    válasz pmonitor #9364 üzenetére

    Köszi! Mint kiderült a "perc" label-t balra, a benne lévő szöveget jobbra, a másodpercet meg pont fordítva kell igazítani, és egyből jó lett.

Új hozzászólás Aktív témák

Hirdetés