using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication14
{
public partial class Form1 : Form
{
int NROWS = 5;
int NCOLS = 3;
public Form1()
{
InitializeComponent();
for (int i = 0; i < NCOLS; i++)
{
for (int j = 0; j < NROWS; j++)
{
Label miaLabel = new Label();
miaLabel.Text = "Ciccia";
miaLabel.BorderStyle = BorderStyle.FixedSingle;
miaLabel.Left = i * miaLabel.Width;
miaLabel.Top = j * miaLabel.Height;
Controls.Add(miaLabel);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Ed ecco l'output, esattamente uguale a quello realizzato in VB.
Queste non sono lezioni, ma appunti che prendo, da non professionista del campo ma da semplice appassionato, per facilitarmi lo studio della programmazione, quindi possono contenere, e in effetti contengono, diversi errori e improprietà, che poi correggo, quando me ne accorgo, con i miei progressi. Per questo non sono assolutamente da prendere per oro colato, ma anzi con molto senso critico.
Visualizzazione post con etichetta C#. Mostra tutti i post
Visualizzazione post con etichetta C#. Mostra tutti i post
lunedì 5 gennaio 2015
Una griglia di caselle anche in C#
E facciamo la stessa cosa in C#: una griglia di caselle.
lunedì 29 dicembre 2014
Scrivere un file XML con il C#
Ho trovato il modo di scrivere un file XML direttamente da un programma fatto con iln C#.
Resta da studiare la cosa e da elaborare anche un programma per la lettura.
private void button1_Click(object sender, EventArgs e)
{
XmlTextWriter writer = new XmlTextWriter("C:/Users/Antonello/product.xml", System.Text.Encoding.UTF8);
writer.WriteStartDocument(true);
writer.Formatting = Formatting.Indented;
writer.Indentation = 2;
writer.WriteStartElement("Table");
createNode("1", "Product 1", "1000", writer);
createNode("2", "Product 2", "2000", writer);
createNode("3", "Product 3", "3000", writer);
createNode("4", "Product 4", "4000", writer);
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Close();
MessageBox.Show("XML File created ! ");
}
private void createNode(string pID, string pName, string pPrice, XmlTextWriter writer)
{
writer.WriteStartElement("Product");
writer.WriteStartElement("Product_id");
writer.WriteString(pID);
writer.WriteEndElement();
writer.WriteStartElement("Product_name");
writer.WriteString(pName);
writer.WriteEndElement();
writer.WriteStartElement("Product_price");
writer.WriteString(pPrice);
writer.WriteEndElement();
writer.WriteEndElement();
}
Il file può essere creato dovunque.Resta da studiare la cosa e da elaborare anche un programma per la lettura.
venerdì 26 dicembre 2014
Disegnare triangoli in Direct3D senza VertexBuffer
Disegno triangoli soltanto definendo un array di vertici.
Questo è il codice che definisce i vertici.
Se non si usa vertexBuffer bisogna specificare i vertici uno dopo l'altro anche se sono uguali.
Una volta specificati i vertici, di tipo CustomVertex.PositionColored, si usa il comando che li stampa:
Ecco l'immagine:
Ma se io uso device.DrawUserPrimitives specificando un numero inferiore di primitive:
Questo è il codice che definisce i vertici.
public void CreaVertici()
{
vertices = new CustomVertex.PositionColored[9];
vertices[0].Position = new Vector3(0f, 0f, 0f);
vertices[0].Color = Color.Blue.ToArgb();
vertices[1].Position = new Vector3(0f, 10f, 0f);
vertices[1].Color = Color.Blue.ToArgb();
vertices[2].Position = new Vector3(10f, 0f, 0f);
vertices[2].Color = Color.Blue.ToArgb();
vertices[3].Position = new Vector3(5f, 0f, 0f);
vertices[3].Color = Color.Green.ToArgb();
vertices[4].Position = new Vector3(5f, 15f, 0f);
vertices[4].Color = Color.Green.ToArgb();
vertices[5].Position = new Vector3(15f, 0f, 0f);
vertices[5].Color = Color.Green.ToArgb();
vertices[6].Position = new Vector3(0f, -10f, 0f);
vertices[6].Color = Color.Red.ToArgb();
vertices[7].Position = new Vector3(18f, -15f, 0f);
vertices[7].Color = Color.Red.ToArgb();
vertices[8].Position = new Vector3(15f, 8f, 0f);
vertices[8].Color = Color.Red.ToArgb();
}
Il numero evidenziato in rosso su giallo è il numero di vertici compresi nell'array,Se non si usa vertexBuffer bisogna specificare i vertici uno dopo l'altro anche se sono uguali.
Una volta specificati i vertici, di tipo CustomVertex.PositionColored, si usa il comando che li stampa:
private void render()
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 3, vertices);
device.EndScene();
device.Present();
}
Ecco, quello marcato in rosso è il comando fondamentale, che stampa i triangoli specificando:
- Il tipo di primitiva
- Il numero di primitive
- l'array di vertici da usare.
Ecco l'immagine:
Ma se io uso device.DrawUserPrimitives specificando un numero inferiore di primitive:
private void render()
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
device.EndScene();
device.Present();
}
Ottengo questa immagine:
domenica 21 dicembre 2014
DirectX
Codice che ho ricavato finora:
Nel costruttore viene chiamata solo InitializeComponent, che si trova nell'altro mezzo modulo con la mezza classe form...
Poi ho marcato in colori diversi i metodi fondamentali dell'oggetto che mi servono.
Sono quattro:
I quattro vengono richiamati nel metodo Main()
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
namespace DirectXProject
{
public partial class mioForm : Form
{
public Device device;
private float angle = 0f;
CustomVertex.PositionColored[] vertices;
public mioForm()
{
InitializeComponent();
}
public void InitializeDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.BackBufferCount = 1;
presentParams.BackBufferFormat = Manager.Adapters[0].CurrentDisplayMode.Format;
presentParams.BackBufferWidth =1366;
presentParams.BackBufferHeight =768;
presentParams.Windowed = false;
presentParams.FullScreenRefreshRateInHz = Manager.Adapters[0].CurrentDisplayMode.RefreshRate;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}
public void CreaVertici()
{
vertices= new CustomVertex.PositionColored[3];
vertices[0].Position = new Vector3(0f, 0f, 0f);
vertices[0].Color = Color.Red.ToArgb();
vertices[1].Position = new Vector3(0f, 10f, 0f);
vertices[1].Color = Color.Red.ToArgb();
vertices[2].Position = new Vector3(10f, 0f, 0f);
vertices[2].Color = Color.Red.ToArgb();
}
public void Camera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 100f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0, 0, -50), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
device.RenderState.Lighting = false;
device.RenderState.CullMode = Cull.None;
}
private void render()
{
device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
device.Transform.World = Matrix.RotationX(angle) * Matrix.RotationZ(angle);
device.DrawUserPrimitives(PrimitiveType.TriangleList,1,vertices);
device.EndScene();
device.Present();
angle += 0.1f;
}
public static void Main()
{
mioForm frm = new mioForm();
frm.WindowState = FormWindowState.Maximized;
frm.InitializeDevice();
frm.CreaVertici();
frm.Camera();
frm.Show();
while (frm.Created)
{
frm.render();
Application.DoEvents();
}
}
private void mioForm_Load(object sender, EventArgs e)
{
}
private void mioForm_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
A parte l'effetto ameno di un triangolo rosso che ruota in modo un po' pazzoide, cerchiamo di analizzare il codice...Nel costruttore viene chiamata solo InitializeComponent, che si trova nell'altro mezzo modulo con la mezza classe form...
Poi ho marcato in colori diversi i metodi fondamentali dell'oggetto che mi servono.
Sono quattro:
- Uno che crea il Device
- Uno che crea i Vertici
- Uno che setta la Telecamera
- Uno che dà l'avvio al disegno.
I quattro vengono richiamati nel metodo Main()
sabato 13 dicembre 2014
Studio di uno scheletro generale per un'applicazione DirectX
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
namespace DirectXProject
{
public partial class mioForm : Form
{
public Device device;
CustomVertex.PositionColored[] vertices;
public mioForm()
{
InitializeComponent();
}
public void InitializeDevice()
{
angle = 0f;
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}
public void CreaVertici()
{
vertices= new CustomVertex.PositionColored[3];
vertices[0].Position = new Vector3(0f, 0f, 0f);
vertices[0].Color = Color.Red.ToArgb();
vertices[1].Position = new Vector3(10f, 0f, 0f);
vertices[1].Color = Color.Green.ToArgb();
vertices[2].Position = new Vector3(5f, 10f, 0f);
vertices[2].Color = Color.Yellow.ToArgb();
}
public void Camera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0, 0, -30), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
device.RenderState.Lighting = false;
device.RenderState.CullMode = Cull.None;
}
protected override void OnPaint(PaintEventArgs e)
{
device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);
device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 1, vertices);
device.EndScene();
device.Present();
}
public static void Main()
{
mioForm frm = new mioForm();
frm.InitializeDevice();
frm.CreaVertici();
frm.Camera();
Application.Run(frm);
}
}
}
Dunque il metodo CreaVertici(), che ho creato io, non fa altro che inizializzare un array di vertici del tipo PositionColored.Il metodo Camera(), sempre creato da me, non fa che posizionare la telecamera, il punto di osservazione.
Il metodo Main chiama questi metodi che preparano i vertici e la telecamera, e quindi inizia il metodon OnPaint, nel quale:
- Si dice al device qual è il formato dei vertici.
- Si dice quale primitiva usare e la matrice di vertici da prendere in considerazione.
lunedì 8 dicembre 2014
Gestori di eventi e delegati.
Nell'ambito di una classe è dichiarato l'evento, con il nome preceduto dall'handler.
Nell'ambito della stessa classe viene dichiarato il delegato, ossia l'handler.
Cerchiamo di interpretare con parole "umane": l'evento viene dichiarato con il nome dell'handler.
L'handler, essendo dichiarato come delegato, esprime la sua firma, ossia il numero e il tipo di parametri. Questo significa che quel dato evento può essere gestito solo da funzioni che abbiano quella firma.
Quindi con la dichiarazione del delegato noi non facciamo altro che esprimere il fatto che quel gestore di eventi, che gestisce quel dato evento, può essere espressione soltanto di funzioni con una determinata firma.
Proviamo:
Più semplice di così...
Ora, però, mettiamo nella nostra classe una funzione che evochi l'evento...
Ora dalla classe principale proviamo a istanziare questa classe.
Bene. Dunque nella classe che esprime l'evento si esprime, tramite il delegato/handler, il tipo di funzione che dovrà gestire l'evento. Punto.
Poi, in un'altra classe, si può verificare l'evento associando all'evento una funzione che abbia la giusta firma.
Spero di aver capito...
class altraClasse
{
public event mioHandler Evento;
}
che ancora mi dà errore perché quel mioHandler non significa ancora nulla.Nell'ambito della stessa classe viene dichiarato il delegato, ossia l'handler.
Cerchiamo di interpretare con parole "umane": l'evento viene dichiarato con il nome dell'handler.
L'handler, essendo dichiarato come delegato, esprime la sua firma, ossia il numero e il tipo di parametri. Questo significa che quel dato evento può essere gestito solo da funzioni che abbiano quella firma.
Quindi con la dichiarazione del delegato noi non facciamo altro che esprimere il fatto che quel gestore di eventi, che gestisce quel dato evento, può essere espressione soltanto di funzioni con una determinata firma.
Proviamo:
class altraClasse
{
public event mioHandler Evento;
public delegate void mioHandler();
}
Ecco, il mio handler, o delegato, non ha parametri.Più semplice di così...
Ora, però, mettiamo nella nostra classe una funzione che evochi l'evento...
class altraClasse
{
public event mioHandler Evento;
public delegate void mioHandler();
public void Evoca()
{
Evento();
}
}
Bene.Ora dalla classe principale proviamo a istanziare questa classe.
public static void Main()
{
altraClasse cs = new altraClasse();
}
Ora, dopo che nel contesto dell'altra classe è stato stabilito che l'evento va gestito da una funzione avente la firma definita dall'handler (delegato), in questa classe si sostituisce al delegato una funzione esistente che abbia la stessa firma, ossia Scrivi().
public static void Main()
{
altraClasse cs = new altraClasse();
cs.Evento += new altraClasse.mioHandler(Scrivi);
cs.Evoca();
}
Quindi si evoca l'evento, e funziona.Bene. Dunque nella classe che esprime l'evento si esprime, tramite il delegato/handler, il tipo di funzione che dovrà gestire l'evento. Punto.
Poi, in un'altra classe, si può verificare l'evento associando all'evento una funzione che abbia la giusta firma.
Spero di aver capito...
domenica 7 dicembre 2014
Array di controlli in C#
Ho realizzato un array di controlli.
Ecco il codice:
Per il momento, passo ad altro.
Ecco il codice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace Project10
{
class mioForm:Form
{
Button[] bottone;
public mioForm()
{
InitializeComponent();
}
public static void Main()
{
mioForm frm = new mioForm();
Application.Run(frm);
}
private void InitializeComponent()
{
bottone = new Button[23];
this.SuspendLayout();
for (int n = 0; n < 23; n++)
{
bottone[n] = new Button();
bottone[n].Width = 50;
bottone[n].Height = 50;
bottone[n].Left = bottone[n].Width * (n % 5);
bottone[n].Top = bottone[n].Height * (n / 5);
bottone[n].Text = (n+1).ToString();
this.Controls.Add(bottone[n]);
}
this.ClientSize = new System.Drawing.Size(584, 561);
this.Name = "mioForm";
this.Load += new System.EventHandler(this.mioForm_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
private void mioForm_Load(object sender, EventArgs e)
{
}
}
}
Resta ancora da vedere come gestire l'evento Click di ciascuno dei controlli, altrimenti che ci faccio?Per il momento, passo ad altro.
Creazione dal nulla di un'applicazione con un form in C#
Apro un progetto vuoto.
Ci aggiungo i riferimenti (System.Windows.Forms) e li collego al programma;
aggiungo una classe mioForm.cs;
Ora dichiaro e istanzio la mia classe derivata da Form, e faccio partire l'applicazione con il mio oggetto:
Ecco che mi viene fuori un codice generato automaticamente:
Bene.
Il codice che si genera automaticamente una volta che viene fatto "partire" il form è:
Però questo codice non viene eseguito all'atto della creazione del form.
Provo a cambiare il tipo di applicazione da "Applicazione Console" a "Applicazione WindowsForm" e ugualmente noto che il codice non viene eseguito, in quanto se cambio i parametri non risultano modificati.
Cambio le dimensioni del form:
Dunque devo ricreare il costruttore del form e metterci dentro la chiamata a InitializeComponent():
Ci aggiungo i riferimenti (System.Windows.Forms) e li collego al programma;
aggiungo una classe mioForm.cs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
class mioForm
{
}
}
Adesso faccio ereditare la mia classe dalla classe Form.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
class mioForm:Form
{
}
}
Aggiungo il metodo statico Main();
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
class mioForm:Form
{
public static void Main()
{
}
}
}
Facendo partire questo, ottengo solo una fugace visualizzazione di una console.Ora dichiaro e istanzio la mia classe derivata da Form, e faccio partire l'applicazione con il mio oggetto:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
class mioForm:Form
{
public static void Main()
{
mioForm frm = new mioForm();
Application.Run(frm);
}
}
}
Ottengo una console e un form, che resta lì e devo chiudere con la "crocetta" in alto a destra per terminare l'esecuzione.Ecco che mi viene fuori un codice generato automaticamente:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Project10
{
class mioForm:Form
{
public static void Main()
{
mioForm frm = new mioForm();
Application.Run(frm);
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// mioForm
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "mioForm";
this.Load += new System.EventHandler(this.mioForm_Load);
this.ResumeLayout(false);
}
private void mioForm_Load(object sender, EventArgs e)
{
}
}
}
In più mi viene fuori un errore relativo al Drawing:
Errore 1 Il tipo 'System.Drawing.Size' è definito in un assembly di cui manca il riferimento. Aggiungere un riferimento all'assembly 'System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. c:\users\antonello\documents\visual studio 2010\Projects\Project10\Project10\mioForm.cs 24 13 Project10 Errore 2 Il tipo o il nome dello spazio dei nomi 'Drawing' non esiste nello spazio dei nomi 'System'; probabilmente manca un riferimento a un assembly c:\users\antonello\documents\visual studio 2010\Projects\Project10\Project10\mioForm.cs 24 42 Project10Introduco il riferimento a Drawing...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
Adesso funziona di nuovo.Bene.
Il codice che si genera automaticamente una volta che viene fatto "partire" il form è:
private void InitializeComponent()
{
this.SuspendLayout();
//
// mioForm
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "mioForm";
this.Load += new System.EventHandler(this.mioForm_Load);
this.ResumeLayout(false);
}
private void mioForm_Load(object sender, EventArgs e)
{
}
ossia il codice che inizializza il Form.Però questo codice non viene eseguito all'atto della creazione del form.
Provo a cambiare il tipo di applicazione da "Applicazione Console" a "Applicazione WindowsForm" e ugualmente noto che il codice non viene eseguito, in quanto se cambio i parametri non risultano modificati.
Cambio le dimensioni del form:
private void InitializeComponent()
{
this.SuspendLayout();
//
// mioForm
//
this.ClientSize = new System.Drawing.Size(584, 261);
this.Name = "mioForm";
this.Load += new System.EventHandler(this.mioForm_Load);
this.ResumeLayout(false);
}
private void mioForm_Load(object sender, EventArgs e)
{
}
e il form mi viene sempre delle dimensioni standard.Dunque devo ricreare il costruttore del form e metterci dentro la chiamata a InitializeComponent():
class mioForm:Form
{
public mioForm()
{
InitializeComponent();
}
public static void Main()
{
mioForm frm = new mioForm();
Application.Run(frm);
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// mioForm
//
this.ClientSize = new System.Drawing.Size(584, 261);
this.Name = "mioForm";
this.Load += new System.EventHandler(this.mioForm_Load);
this.ResumeLayout(false);
}
private void mioForm_Load(object sender, EventArgs e)
{
}
}
e adesso il form mi viene delle nuove dimensioni!sabato 6 dicembre 2014
Pagina web di riferimento
Il device è quello che dà accesso diretto all'adattatore grafico.
Diretto accesso all'hardware.
Ovviamente, il device va dichiarato.
E su questo non abbiamo problemi.
Una volta dichiarato, come per tutte le variabili, bisogna istanziarlo.
Quindi sarà d'obbligo usare qualcosa tipo device = new Device(....).
Vediamo come.
Credo che sia il caso di istanziarlo nel costruttore.
mmmhhh... mi sa che qui viene istanziato nel metodo Main...
Ma andiamo per gradi.
Il costruttore del Device richiede come parametri PresentationParameters, e quindi viene creato un metodo InitializeDevice che setta i parametri e inizializza il device.
Quindi il costruttore del device richiede una serie di parametri, che magari vedo successivamente.
Per il momento mi basta aver dichiarato e istanziato il device con questi due pezzi di codice: la dichiarazione nel contesto delle variabili del form e l'istanziazione (inizializzazione) nel contesto del metodo InitializeDevice().
Ora inserisco il richiamo al metodo InitializeDevice() nel metodo Main() e poi avvio, e funziona.
C'è solo un form, uno stupidissimo form del tutto normale. Però dovrebbe essere stato creato un device.
Mi fido sulla parola!
Il device è quello che dà accesso diretto all'adattatore grafico.
Diretto accesso all'hardware.
Ovviamente, il device va dichiarato.
E su questo non abbiamo problemi.
namespace WindowsFormsApplication12
{
public partial class Form1 : Form
{
private Device device;
public Form1()
{
InitializeComponent();
}
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Bene.Una volta dichiarato, come per tutte le variabili, bisogna istanziarlo.
Quindi sarà d'obbligo usare qualcosa tipo device = new Device(....).
Vediamo come.
Credo che sia il caso di istanziarlo nel costruttore.
mmmhhh... mi sa che qui viene istanziato nel metodo Main...
Ma andiamo per gradi.
Il costruttore del Device richiede come parametri PresentationParameters, e quindi viene creato un metodo InitializeDevice che setta i parametri e inizializza il device.
public void InitializeDevice()
{
PresentParameters presentparams = new PresentParameters();
presentparams.Windowed = true;
presentparams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentparams);
}
Ecco, i parametri vanno inizializzati soltanto relativamente ad "applicazione a finestra", ossia non fullscreen, e a "scartare lo swapeffect", che a quanto ho capito consiste nello scrivere nel dispositivo mediante un buffer che viene presentato a runtime.Quindi il costruttore del device richiede una serie di parametri, che magari vedo successivamente.
Per il momento mi basta aver dichiarato e istanziato il device con questi due pezzi di codice: la dichiarazione nel contesto delle variabili del form e l'istanziazione (inizializzazione) nel contesto del metodo InitializeDevice().
Ora inserisco il richiamo al metodo InitializeDevice() nel metodo Main() e poi avvio, e funziona.
C'è solo un form, uno stupidissimo form del tutto normale. Però dovrebbe essere stato creato un device.
Mi fido sulla parola!
mercoledì 3 dicembre 2014
Brancolando nel buio con il DirectX senza un'adeguata preparazione sul C#
Credo di aver trovato un tutorial piuttosto valido...
Cominciamo a seguirlo, tentando di ricordare e rafforzare il mio approccio di apprendimento...
Per prima cosa, stando al tutorial, devo aprire un progetto di C# tipo Window...
Proviamo...
Fatto.
Ora aggiungiamo i riferimenti.
Fatto.
Inseriamo le linee di codice per l'uso delle librerie referenziate.
Adesso il tutorial dice di variare le dimensioni del form e il suo nome... giusto a titolo di esercizio.
Facciamolo.
Si fa dal metodo InitializeComponents(). Ora, InitializeComponents viene chiamato dal costruttore del form, ma non è presente sul modulo principale del form, bensì su quello chiamato Designer,dove c'è l'altra parte della partial class del Form...
Lo apro e ce lo trovo...
Adesso mi dice di modificare la Main...
Bene, ho problemi perché avendo aperto un'applicazione tipo Windows non ho una Main...
Retrocediamo e studiamo un po' come si può avere un inizio da una Main che istanzia un form, anziché da un form stesso.
Cominciamo a seguirlo, tentando di ricordare e rafforzare il mio approccio di apprendimento...
Per prima cosa, stando al tutorial, devo aprire un progetto di C# tipo Window...
Proviamo...
Fatto.
Ora aggiungiamo i riferimenti.
Fatto.
Inseriamo le linee di codice per l'uso delle librerie referenziate.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace DirectX
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
Bene.Adesso il tutorial dice di variare le dimensioni del form e il suo nome... giusto a titolo di esercizio.
Facciamolo.
Si fa dal metodo InitializeComponents(). Ora, InitializeComponents viene chiamato dal costruttore del form, ma non è presente sul modulo principale del form, bensì su quello chiamato Designer,dove c'è l'altra parte della partial class del Form...
Lo apro e ce lo trovo...
namespace DirectX
{
partial class Form1
{
///
/// Variabile di progettazione necessaria.
///
private System.ComponentModel.IContainer components = null;
///
/// Liberare le risorse in uso.
///
/// ha valore true se le risorse gestite devono essere eliminate, false in caso contrario.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Codice generato da Progettazione Windows Form
///
/// Metodo necessario per il supporto della finestra di progettazione. Non modificare
/// il contenuto del metodo con l'editor di codice.
///
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
}
}
Provo a modificare, in questo metodo, i parametri.
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(500, 500);
this.Name = "Form1";
this.Text = "Form del cavolo";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
Nessun problema...Adesso mi dice di modificare la Main...
Bene, ho problemi perché avendo aperto un'applicazione tipo Windows non ho una Main...
Retrocediamo e studiamo un po' come si può avere un inizio da una Main che istanzia un form, anziché da un form stesso.
lunedì 1 dicembre 2014
Primi passi con il device (DirectX) in C#
Diamo una definizione di polimorfismo.
Un oggetto di un tipo può assumere valori di un tipo derivato dal suo tipo.
Un parametro di un certo tipo può essere sostituito da un parametro di un tipo derivato.
Dunque quando nel metodo OnPaint di un oggetto di classe derivata da form si mette la parola chiave override questo significa che questo metodo overridda (scavalca) quello della classe base.
Questo OnPaint è un metodo, non un evento.
Ma adesso trovo un codice diverso che non fa uso di OnPaint...
Il nucleo di questo codice è:
Quindi chiama initGraphics che è il metodo nel quale viene creato il device.
Che roba è?
Mentre il controllo esiste, si eseguono le successive istruzioni comprese fra parentesi graffe...
Se provo a sostituire while con if, il form sparisce, probabilmente perché la condizione di esistenza del form viene verificata solo una volta.
Quindi riassumendo inizialmente si crea il device, quindi si mostra il form e mentre il form esiste si esegue il metodo Render, che "aziona" il device evocandone dei metodi che portano al mostrare il form con certe caratteristiche...
Cominciamo a decifrare...
Un oggetto di un tipo può assumere valori di un tipo derivato dal suo tipo.
Un parametro di un certo tipo può essere sostituito da un parametro di un tipo derivato.
Dunque quando nel metodo OnPaint di un oggetto di classe derivata da form si mette la parola chiave override questo significa che questo metodo overridda (scavalca) quello della classe base.
Questo OnPaint è un metodo, non un evento.
Ma adesso trovo un codice diverso che non fa uso di OnPaint...
Il nucleo di questo codice è:
static void Main()
{
MioForm frm = new MioForm();
frm.initGraphics();
frm.Show();
while(frm.Created){
frm.Render();
Application.DoEvents();
}
}
La prima riga del metodo non fa altro che istanziare un nuovo frm di classe MioForm la quale è una classe derivata da Form.Quindi chiama initGraphics che è il metodo nel quale viene creato il device.
void initGraphics()
{
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SwapEffect.Discard;
dispositivo = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);
}
Quindi si mostra il form, semplicemente:
frm.Show();e quindi si usa frm.Created.
Che roba è?
Mentre il controllo esiste, si eseguono le successive istruzioni comprese fra parentesi graffe...
Se provo a sostituire while con if, il form sparisce, probabilmente perché la condizione di esistenza del form viene verificata solo una volta.
while(frm.Created){
frm.Render();
Application.DoEvents();
}
Quindi riassumendo inizialmente si crea il device, quindi si mostra il form e mentre il form esiste si esegue il metodo Render, che "aziona" il device evocandone dei metodi che portano al mostrare il form con certe caratteristiche...
Cominciamo a decifrare...
sabato 29 novembre 2014
Creazione del device (DirectX): si inizia brancolando nel buio...
Dichiariamo un device.
Non so ancora niente sul significato di queste cose, che approfondirò successivamente.
Obiettivo: studiare i parametri della creazione del device.
Cosa rappresentano i parametri del costruttore del device?
Dunque... Inizio a parlare per tentativi, mettendo a punto quel poco che ho capito in attesa di chiarificazione (in omaggio al principio che quando i bambini iniziano a parlare non studiano l'analisi logica e grammaticale).
Il primo parametro è un numero che fa riferimento al device fisico. E' uno in meno del numero dei devices.
Il secondo parametro è il tipo di device, che può essere hardware o software (arabo puro... almeno per il momento)
Il terzo parametro identifica la finestra da collegare al device, che in questo caso è this nel senso che è il qui presente form
Il quarto parametro è il tipo di comportamento delle Flags (per me al momento è arabo antico purissimo... ma non disperiamo)
Il quinto parametro sono i parametri di presentazione che abbiamo definito poco fa.
Bene.
Dunque mi pare di intravvedere una qualche logica pur nella nebulosità della situazione.
Prima si identifica questo fantomatico dispositivo fisico, quindi si specifica il tipo di dispositivo (non fisico? Virtuale?...) che si vuole e si fa il collegamento del dispositivo alla finestra.
Successivamente si definiscono le flags (?) e i parametri di presentazione (?).
Ho detto sicuramente un sacco di scemenze, ma ogni cultura inizia dalla scemenza, in fondo...
class MioForm:Form
{
private Device dispositivo=null;
static void Main()
{
MioForm frm = new MioForm();
Application.Run(frm);
}
private void InitializeComponent()
{
this.SuspendLayout();
//
// MioForm
//
this.ClientSize = new System.Drawing.Size(284, 261);
this.Name = "MioForm";
this.Load += new System.EventHandler(this.MioForm_Load);
this.ResumeLayout(false);
}
private void MioForm_Load(object sender, EventArgs e)
{
}
}
}
Ora dovrei creare un metodo InitGraphics.
void initGraphics()
{
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SwapEffect.Discard;
dispositivo = new Device(0,DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);
}
In questo metodo viene creato il dispositivo. Per la creazione del dispositivo, è necessario inserire alcuni parametri, fra i quali PresentParameters, che viene quindi modificato prima della creazione.Non so ancora niente sul significato di queste cose, che approfondirò successivamente.
Obiettivo: studiare i parametri della creazione del device.
Cosa rappresentano i parametri del costruttore del device?
Dunque... Inizio a parlare per tentativi, mettendo a punto quel poco che ho capito in attesa di chiarificazione (in omaggio al principio che quando i bambini iniziano a parlare non studiano l'analisi logica e grammaticale).
Il primo parametro è un numero che fa riferimento al device fisico. E' uno in meno del numero dei devices.
Il secondo parametro è il tipo di device, che può essere hardware o software (arabo puro... almeno per il momento)
Il terzo parametro identifica la finestra da collegare al device, che in questo caso è this nel senso che è il qui presente form
Il quarto parametro è il tipo di comportamento delle Flags (per me al momento è arabo antico purissimo... ma non disperiamo)
Il quinto parametro sono i parametri di presentazione che abbiamo definito poco fa.
Bene.
Dunque mi pare di intravvedere una qualche logica pur nella nebulosità della situazione.
Prima si identifica questo fantomatico dispositivo fisico, quindi si specifica il tipo di dispositivo (non fisico? Virtuale?...) che si vuole e si fa il collegamento del dispositivo alla finestra.
Successivamente si definiscono le flags (?) e i parametri di presentazione (?).
Ho detto sicuramente un sacco di scemenze, ma ogni cultura inizia dalla scemenza, in fondo...
martedì 9 settembre 2014
Interfacce in C#
Ecco: vediamo le interfacce...
Cominciamo dal C#.
Ho due classi, impiegato e scolaro ambedue delle quali hanno la funzione scrivi().
Ognuno esegue la funzione:
Adesso mi serve una funzione in cui si scriva: posso chiamare sia uno scolaro che un impiegato: ambedue implementano l'interfaccia IScrivente
Ma questo lavoro non si può fare con le classi astratte?
Proviamo...
Ma può capitare che una classe implementi più di una interfaccia, e dal momento che in C# non esiste l'ereditarietà multipla come in C++, è conveniente usare le interfacce.
E poi con le classi astratte si possono passare anche metodi già implementati, cosa che non si può fare con le interfacce.
Cominciamo dal C#.
Ho due classi, impiegato e scolaro ambedue delle quali hanno la funzione scrivi().
Ognuno esegue la funzione:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Impiegato
{
public void scrivi()
{
Console.WriteLine("io scrivo i documenti");
Console.ReadLine();
}
public void relaziona()
{
Console.WriteLine("io relaziono sui documenti");
Console.ReadLine();
}
}
class Scolaro
{
public void scrivi()
{
Console.WriteLine("io scrivo i compiti sul quaderno");
Console.ReadLine();
}
public void calcola()
{
Console.WriteLine("io faccio i calcoli per i problemi di matematica");
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Impiegato Mario = new Impiegato();
Scolaro Pierino = new Scolaro();
Mario.scrivi();
Pierino.scrivi();
}
}
}
io scrivo i documenti io scrivo i compiti sul quaderno
Adesso mi serve una funzione in cui si scriva: posso chiamare sia uno scolaro che un impiegato: ambedue implementano l'interfaccia IScrivente
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Impiegato:IScrivente
{
public void scrivi()
{
Console.WriteLine("io scrivo i documenti");
Console.ReadLine();
}
public void relaziona()
{
Console.WriteLine("io relaziono sui documenti");
Console.ReadLine();
}
}
class Scolaro:IScrivente
{
public void scrivi()
{
Console.WriteLine("io scrivo i compiti sul quaderno");
Console.ReadLine();
}
public void calcola()
{
Console.WriteLine("io faccio i calcoli per i problemi di matematica");
Console.ReadLine();
}
}
interface IScrivente
{
void scrivi();
}
class Program
{
static void serveScrittura(IScrivente x)
{
x.scrivi();
}
static void Main(string[] args)
{
Impiegato Mario = new Impiegato();
Scolaro Pierino = new Scolaro();
serveScrittura(Mario);
serveScrittura(Pierino);
}
}
}
io scrivo i documenti io scrivo i compiti sul quadernoEcco. Sia Impiegato che Scolaro implementano l'interfaccia IScrivente. L'unica cosa notevole da ricordare è che la sintassi in C# per implementare l'interfaccia è uguale a quella di rendere una classe derivata di un'altra.
Ma questo lavoro non si può fare con le classi astratte?
Proviamo...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
abstract class Scrivente
{
public abstract void scrivi();
}
class Impiegato:Scrivente
{
public override void scrivi()
{
Console.WriteLine("io scrivo i documenti");
Console.ReadLine();
}
public void relaziona()
{
Console.WriteLine("io relaziono sui documenti");
Console.ReadLine();
}
}
class Scolaro:Scrivente
{
public override void scrivi()
{
Console.WriteLine("io scrivo i compiti sul quaderno");
Console.ReadLine();
}
public void calcola()
{
Console.WriteLine("io faccio i calcoli per i problemi di matematica");
Console.ReadLine();
}
}
class Program
{
static void serveScrittura(Scrivente x)
{
x.scrivi();
}
static void Main(string[] args)
{
Impiegato Mario = new Impiegato();
Scolaro Pierino = new Scolaro();
serveScrittura(Mario);
serveScrittura(Pierino);
}
}
}
io scrivo i documenti io scrivo i compiti sul quadernoCerto che si può.
Ma può capitare che una classe implementi più di una interfaccia, e dal momento che in C# non esiste l'ereditarietà multipla come in C++, è conveniente usare le interfacce.
E poi con le classi astratte si possono passare anche metodi già implementati, cosa che non si può fare con le interfacce.
domenica 7 settembre 2014
Classi astratte comparate nei quattro linguaggi
Andiamo dunque all'eventualità in cui il maestro Cuoco non lavori più.
Egli non è più disponibile per essere istanziato, ossia per svolgere turni al ristorante, ma continua a dirigere il ristorante stesso.
Egli lascia completa libertà su tutto, ma esige che chi lavora per lui faccia il pollo col rosmarino e non in modo diverso.
In C++:
In VB:
In C#:
In Java:
Adesso dobbiamo ripassarci bene overriding e overloading comparati...
Egli non è più disponibile per essere istanziato, ossia per svolgere turni al ristorante, ma continua a dirigere il ristorante stesso.
Egli lascia completa libertà su tutto, ma esige che chi lavora per lui faccia il pollo col rosmarino e non in modo diverso.
In C++:
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pollo(){
cout << "io cucino il pollo con rosmarino" << endl;
getchar();
}
virtual void Pasta(char * condimento)=0;
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino con la pentola a pressione pasta e " << condimento << endl;
getchar();
}
void Pasta(char * condimento, char * condimento2){
cout << "io cucino con la pentola a pressione pasta e " << condimento << " e " << condimento2 << endl;
getchar();
}
};
class Apprendista2: public Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino col forno a legna pasta e " << condimento << endl;
getchar();
}
void Pasta(char * condimento, char * condimento2){
cout << "io cucino con la pentola a pressione pasta e " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void main(){
Apprendista * Antonio=new Apprendista();
Apprendista2 * Giuseppe=new Apprendista2();
Antonio->Pasta("sugo");
Antonio->Pasta("tonno", "formaggio");
Antonio->Pollo();
Giuseppe->Pasta("sugo");
Giuseppe->Pasta("aglio", "olio");
Giuseppe->Pollo();
}
io cucino con la pentola a pressione pasta e sugo io cucino con la pentola a pressione pasta e tonno e formaggio io cucino il pollo con rosmarino io cucino col forno a legna pasta e sugo io cucino con la pentola a pressione pasta e aglio e olio io cucino il pollo con rosmarino
In VB:
Module Module1
MustInherit Class Cuoco
Public Sub Pollo()
Console.WriteLine("io cucino il pollo col rosmarino")
Console.ReadLine()
End Sub
Public MustOverride Sub Pasta(condimento As String)
End Class
Class Apprendista
Inherits Cuoco
Public Overrides Sub Pasta(condimento As String)
Console.WriteLine("io cucino nella pentola a pressione pasta con " & condimento)
Console.ReadLine()
End Sub
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino nella pentola a pressione pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Class Apprendista2
Inherits Cuoco
Public Overrides Sub Pasta(condimento As String)
Console.WriteLine("io cucino col forno a legna a pressione pasta con " & condimento)
Console.ReadLine()
End Sub
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino col forno a legna pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub Main()
Dim Antonio As New Apprendista
Dim Giuseppe As New Apprendista2
Antonio.Pasta("sugo")
Antonio.Pasta("tonno", "formaggio")
Antonio.Pollo()
Giuseppe.Pasta("sugo")
Giuseppe.Pasta("aglio", "olio")
Giuseppe.Pollo()
End Sub
End Module
io cucino nella pentola a pressione pasta con sugo io cucino nella pentola a pressione pasta con tonno e formaggio io cucino il pollo col rosmarino io cucino col forno a legna a pressione pasta con sugo io cucino col forno a legna pasta con aglio e olio io cucino il pollo col rosmarino
In C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
abstract class Cuoco
{
public void Pollo()
{
Console.WriteLine("io cucino il pollo col rosmarino");
Console.ReadLine();
}
abstract public void Pasta(string condimento);
}
class Apprendista : Cuoco
{
public override void Pasta(string condimento)
{
Console.WriteLine("io cucino nella pentola a pressione pasta con " + condimento);
Console.ReadLine();
}
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino nella pentola a pressione la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Apprendista2 : Cuoco
{
public override void Pasta(string condimento)
{
Console.WriteLine("io cucino nel forno a legna pasta con " + condimento);
Console.ReadLine();
}
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino nel forno a legna la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Apprendista Antonio = new Apprendista();
Apprendista2 Giuseppe = new Apprendista2();
Antonio.Pasta("sugo");
Antonio.Pasta("tonno", "formaggio");
Antonio.Pollo();
Giuseppe.Pasta("sugo");
Giuseppe.Pasta("aglio", "olio");
Giuseppe.Pollo();
}
}
}
io cucino nella pentola a pressione pasta con sugo io cucino nella pentola a pressione la pasta con tonno e formaggio io cucino il pollo col rosmarino io cucino nel forno a legna pasta con sugo io cucino nel forno a legna la pasta con aglio e olio io cucino il pollo col rosmarino
In Java:
package javaapplication1;
abstract class Cuoco{
public void Pollo(){
System.out.println("io cucino il pollo col rosmarino");
}
public abstract void Pasta(String condimento);
}
class Apprendista extends Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino nella pentola a pressione pasta con "+ condimento);
}
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino nella pentola a pressione pasta con " + condimento + " e "+ condimento2);
}
}
class Apprendista2 extends Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino nel forno a legna pasta con "+ condimento);
}
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino nel forno a legna pasta con " + condimento + " e "+ condimento2);
}
}
public class JavaApplication1 {
public static void main(String[] args) {
Apprendista Antonio=new Apprendista();
Apprendista2 Giuseppe=new Apprendista2();
Antonio.Pasta("sugo");
Antonio.Pasta("tonno","formaggio");
Antonio.Pollo();
Giuseppe.Pasta("sugo");
Giuseppe.Pasta("aglio","olio");
Giuseppe.Pollo();
}
}
run: io cucino nella pentola a pressione pasta con sugo io cucino nella pentola a pressione pasta con tonno e formaggio io cucino il pollo col rosmarino io cucino nel forno a legna pasta con sugo io cucino nel forno a legna pasta con aglio e olio io cucino il pollo col rosmarino BUILD SUCCESSFUL (total time: 0 seconds)Ecco.
Adesso dobbiamo ripassarci bene overriding e overloading comparati...
sabato 6 settembre 2014
Metodi virtuali nei 4 linguaggi.
Adesso anche l'apprendista vuole essere chiamato Cuoco perché si sente un Cuoco a tutti gli effetti.
Dunque ricostruiamo la funzione che chiama ambedue con lo stesso nome, rispettando però il diverso modo di lavorare dell'apprendista.
In VB:
in C#:
in Java:
Bene.
Tranne che in Java, in tutti gli altri linguaggi il vecchio Maestro chiama Cuoco l'apprendista ma lo obbliga a usare i suoi metodi, ossia cucinare senza la pentola a pressione!
Poi si arrende, e scende a più miti consigli, ma per farlo sono necessari i metodi virtuali:
In C++:
in VB:
in C#:
in Java il problema è già risolto alla base. Mi chiedo se ci siano situazioni in cui sia necessario che il metodo della classe derivata NON overriddi quello della classe base, e in tal caso come si faccia.
Dunque ricostruiamo la funzione che chiama ambedue con lo stesso nome, rispettando però il diverso modo di lavorare dell'apprendista.
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino nella pentola a pressione pasta con " << condimento << endl;
getchar();
}
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void chiama(Cuoco * x){
x->Pasta("sugo");
}
void main(){
Cuoco * Mario = new Cuoco();
Apprendista * Antonio=new Apprendista();
chiama(Mario);
chiama(Antonio);
}
io cucino pasta con sugo io cucino pasta con sugo
In VB:
Module Module1
Class Cuoco
Public Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Overloads Sub Pasta(condimento As String)
Console.WriteLine("io cucino nella pentola a pressione pasta con " & condimento)
Console.ReadLine()
End Sub
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub chiama(x As Cuoco)
x.Pasta("sugo")
End Sub
Sub Main()
Dim Mario As New Cuoco
Dim Antonio As New Apprendista
chiama(Mario)
chiama(Antonio)
End Sub
End Module
io cucino pasta con sugo io cucino pasta con sugo
in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino la pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino nella pentola a pressione pasta con " + condimento);
Console.ReadLine();
}
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void chiama(Cuoco x)
{
x.Pasta("sugo");
}
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
chiama(Mario);
chiama(Antonio);
}
}
}
io cucino la pasta con sugo io cucino la pasta con sugo
in Java:
package javaapplication1;
class Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino pasta con " + condimento);
}
}
class Apprendista extends Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino nella pentola a pressione pasta con "+ condimento);
}
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino pasta con " + condimento + " e "+ condimento2);
}
}
public class JavaApplication1 {
static void chiama(Cuoco x){
x.Pasta("sugo");
}
public static void main(String[] args) {
Cuoco Mario=new Cuoco();
Apprendista Antonio=new Apprendista();
chiama(Mario);
chiama(Antonio);
}
}
run: io cucino pasta con sugo io cucino nella pentola a pressione pasta con sugo BUILD SUCCESSFUL (total time: 0 seconds)
Bene.
Tranne che in Java, in tutti gli altri linguaggi il vecchio Maestro chiama Cuoco l'apprendista ma lo obbliga a usare i suoi metodi, ossia cucinare senza la pentola a pressione!
Poi si arrende, e scende a più miti consigli, ma per farlo sono necessari i metodi virtuali:
In C++:
#include "iostream"
using namespace std;
class Cuoco{
public:
virtual void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino nella pentola a pressione pasta con " << condimento << endl;
getchar();
}
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void chiama(Cuoco * x){
x->Pasta("sugo");
}
void main(){
Cuoco * Mario = new Cuoco();
Apprendista * Antonio=new Apprendista();
chiama(Mario);
chiama(Antonio);
}
io cucino pasta con sugo io cucino nella pentola a pressione pasta con sugo
in VB:
Module Module1
Class Cuoco
Public Overridable Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Overrides Sub Pasta(condimento As String)
Console.WriteLine("io cucino nella pentola a pressione pasta con " & condimento)
Console.ReadLine()
End Sub
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub chiama(x As Cuoco)
x.Pasta("sugo")
End Sub
Sub Main()
Dim Mario As New Cuoco
Dim Antonio As New Apprendista
chiama(Mario)
chiama(Antonio)
End Sub
End Module
io cucino pasta con sugo io cucino nella pentola a pressione pasta con sugo
in C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public virtual void Pasta(string condimento)
{
Console.WriteLine("io cucino la pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public override void Pasta(string condimento)
{
Console.WriteLine("io cucino nella pentola a pressione pasta con " + condimento);
Console.ReadLine();
}
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void chiama(Cuoco x)
{
x.Pasta("sugo");
}
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
chiama(Mario);
chiama(Antonio);
}
}
}
io cucino la pasta con sugo io cucino nella pentola a pressione pasta con sugo
in Java il problema è già risolto alla base. Mi chiedo se ci siano situazioni in cui sia necessario che il metodo della classe derivata NON overriddi quello della classe base, e in tal caso come si faccia.
Overriding del metodo ereditato nei 4 linguaggi.
Adesso il nostro apprendista elabora un modo suo di cucinare, e si mette a usare la pentola a pressione.
In C++
In VB:
Ho dovuto ridefinire il metodo in C++, e anche in VB.NET.
Però in VB.NET ho dovuto anteporre la parola chiave Overloads anche al metodo ridefinito.
In C#:
in Java:
In C++
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino nella pentola a pressione pasta con " << condimento << endl;
getchar();
}
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void main(){
Cuoco * Mario = new Cuoco();
Apprendista * Antonio=new Apprendista();
Mario->Pasta("ragu");
Antonio->Pasta("ragu");
}
io cucino pasta con ragu io cucino nella pentola a pressione pasta con ragu
In VB:
Module Module1
Class Cuoco
Public Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Overloads Sub Pasta(condimento As String)
Console.WriteLine("io cucino nella pentola a pressione pasta con " & condimento)
Console.ReadLine()
End Sub
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub Main()
Dim Antonio As New Apprendista
Antonio.Pasta("ragu")
End Sub
End Module
io cucino pasta con ragu io cucino nella pentola a pressione pasta con raguEcco.
Ho dovuto ridefinire il metodo in C++, e anche in VB.NET.
Però in VB.NET ho dovuto anteporre la parola chiave Overloads anche al metodo ridefinito.
In C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino la pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino nella pentola a pressione pasta con " + condimento);
Console.ReadLine();
}
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
Mario.Pasta("ragu");
Antonio.Pasta("ragu");
}
}
}
io cucino la pasta con ragu io cucino nella pentola a pressione pasta con ragu
in Java:
package javaapplication1;
class Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino pasta con " + condimento);
}
}
class Apprendista extends Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino nella pentola a pressione pasta con "+ condimento);
}
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino pasta con " + condimento + " e "+ condimento2);
}
}
public class JavaApplication1 {
public static void main(String[] args) {
Cuoco Mario=new Cuoco();
Apprendista Antonio=new Apprendista();
Mario.Pasta("ragu");
Antonio.Pasta("ragu");
}
}
run: io cucino pasta con ragu io cucino nella pentola a pressione pasta con ragu BUILD SUCCESSFUL (total time: 1 second)Anche qui il comportamento è simile a quello del C#.
Comparazione in 4 linguaggi dell'overloading di un metodo ereditato.
Oggi il maestro Cuoco è ammalato, e al ristorante c'è solo l'Apprendista, che è ormai abituato a cucinare solo ed esclusivamente pasta a due condimenti.
I clienti apprezzano tutti, anche quelli che a volte preferivano soltanto un semplice piatto di pasta col sugo o pasta col pesto, sapendo che c'è solo l'Apprendista e che lui dà il meglio di sé coi piatti di pasta a due condimenti, si adeguano e ordinano tutti pasta a due condimenti.
Senonché arriva l'anziano sig. Sclerosetti, il quale è un tradizionalista inguaribile, e, abituato a mangiare sempre e solo pasta a un condimento solo, esige che l'Apprendista gli prepari un piatto di pasta col ragù e basta!
L'apprendista si dà da fare, e vediamo che succede nei quattro linguaggi:
In C++:
In VB:
In C#:
In Java:
Ecco: abbiamo messaggi di errore in C++ e in VB.NET.
In C++ avevo risolto ridichiarando il metodo ereditato nella classe derivata.
Ma vediamo se esiste qualche altro modo...
Ecco: ho trovato un altro modo: mettere nella classe derivata un using Base::metodo;.
In VB.NET, invece, bisogna mettere nell'altro metodo la parola chiave Overloads a indicare che il metodo viene overloadato e non overridato... (anche se forse questa non è la parola giusta).
Facciamo la comparazione fra C++ e VB.NET:
In C++:
in VB:
In C# e in Java l'overload è implicito.
I clienti apprezzano tutti, anche quelli che a volte preferivano soltanto un semplice piatto di pasta col sugo o pasta col pesto, sapendo che c'è solo l'Apprendista e che lui dà il meglio di sé coi piatti di pasta a due condimenti, si adeguano e ordinano tutti pasta a due condimenti.
Senonché arriva l'anziano sig. Sclerosetti, il quale è un tradizionalista inguaribile, e, abituato a mangiare sempre e solo pasta a un condimento solo, esige che l'Apprendista gli prepari un piatto di pasta col ragù e basta!
L'apprendista si dà da fare, e vediamo che succede nei quattro linguaggi:
In C++:
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void main(){
Apprendista * Antonio = new Apprendista();
Antonio->Pasta("ragu");
}
1>c:\users\antonello\documents\visual studio 2010\projects\test15\test15\foglio1.cpp(25): error C2660: 'Apprendista::Pasta': la funzione non accetta 1 argomenti
In VB:
Module Module1
Class Cuoco
Public Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub Main()
Dim Antonio As New Apprendista
Antonio.Pasta("ragu")
End Sub
End Module
Errore 2 Argomento non specificato per il parametro 'condimento2' di 'Public Sub Pasta(condimento As String, condimento2 As String)'. C:\Users\Antonello\AppData\Local\Temporary Projects\ConsoleApplication1\Module1.vb 21 9 ConsoleApplication1
In C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino la pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Apprendista Antonio = new Apprendista();
Antonio.Pasta("ragu");
}
}
}
io cucino la pasta con ragu
In Java:
package javaapplication1;
class Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino pasta con " + condimento);
}
}
class Apprendista extends Cuoco{
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino pasta con " + condimento + " e "+ condimento2);
}
}
public class JavaApplication1 {
public static void main(String[] args) {
Apprendista Antonio=new Apprendista();
Antonio.Pasta("ragu");
}
}
run: io cucino pasta con ragu BUILD SUCCESSFUL (total time: 0 seconds)
Ecco: abbiamo messaggi di errore in C++ e in VB.NET.
In C++ avevo risolto ridichiarando il metodo ereditato nella classe derivata.
Ma vediamo se esiste qualche altro modo...
Ecco: ho trovato un altro modo: mettere nella classe derivata un using Base::metodo;.
In VB.NET, invece, bisogna mettere nell'altro metodo la parola chiave Overloads a indicare che il metodo viene overloadato e non overridato... (anche se forse questa non è la parola giusta).
Facciamo la comparazione fra C++ e VB.NET:
In C++:
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
using Cuoco::Pasta;
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void main(){
Apprendista * Antonio = new Apprendista();
Antonio->Pasta("ragu");
}
io cucino pasta con ragu
in VB:
Module Module1
Class Cuoco
Public Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Overloads Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub Main()
Dim Antonio As New Apprendista
Antonio.Pasta("ragu")
End Sub
End Module
io cucino pasta con ragu
In C# e in Java l'overload è implicito.
Ripasso di classi ed ereditarietà, in C++, C#, VB.NET e Java con la storiella del ristorante.
Introduciamo un po' il VB.NET.
Sempre con la scenetta del ristorante.
La vicenda era quella del cuoco che aveva un apprendista, e gli aveva trasmesso la capacità di cucinare la pasta con un condimento.
Ora l'apprendista sviluppa l'abilità di cucinare con due condimenti, che il maestro non ha.
E quindi abbiamo questa situazione:
In VB:
In C#:
In C++
In Java:
Bene.
Da quando l'Apprendista ha elaborato il suo metodo di cucina con due condimenti non cucina più con un solo condimento: dal momento che i due stanno al ristorante insieme, il maestro Cuoco cucina a un condimento, mentre l'Apprendista Antonio cucina a due condimenti.
Vediamo l'ulteriore evoluzione della cosa...
Sempre con la scenetta del ristorante.
La vicenda era quella del cuoco che aveva un apprendista, e gli aveva trasmesso la capacità di cucinare la pasta con un condimento.
Ora l'apprendista sviluppa l'abilità di cucinare con due condimenti, che il maestro non ha.
E quindi abbiamo questa situazione:
In VB:
Module Module1
Class Cuoco
Public Sub Pasta(condimento As String)
Console.WriteLine("io cucino pasta con " & condimento)
Console.ReadLine()
End Sub
End Class
Class Apprendista
Inherits Cuoco
Public Sub Pasta(condimento As String, condimento2 As String)
Console.WriteLine("io cucino pasta con " & condimento & " e " & condimento2)
Console.ReadLine()
End Sub
End Class
Sub Main()
Dim Mario As New Cuoco
Dim Antonio As New Apprendista
Mario.Pasta("sugo")
Antonio.Pasta("aglio", "olio")
End Sub
End Module
io cucino pasta con sugo io cucino pasta con aglio e olio
In C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("io cucino la pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
Mario.Pasta("sugo");
Antonio.Pasta("aglio", "olio");
}
}
}
io cucino la pasta con sugo io cucino la pasta con aglio e olio
In C++
#include "iostream"
using namespace std;
class Cuoco{
public:
void Pasta(char * condimento){
cout << "io cucino pasta con " << condimento << endl;
getchar();
}
};
class Apprendista: public Cuoco{
public:
void Pasta(char * condimento, char * condimento2){
cout << "io cucino pasta con " << condimento << " e " << condimento2 << endl;
getchar();
}
};
void main(){
Cuoco * Mario = new Cuoco();
Apprendista * Antonio = new Apprendista();
Mario->Pasta("sugo");
Antonio->Pasta("aglio","olio");
}
io cucino pasta con sugo io cucino pasta con aglio e olio
In Java:
package javaapplication1;
class Cuoco{
public void Pasta(String condimento){
System.out.println("io cucino pasta con " + condimento);
}
}
class Apprendista extends Cuoco{
public void Pasta(String condimento, String condimento2){
System.out.println("io cucino pasta con " + condimento + " e "+ condimento2);
}
}
public class JavaApplication1 {
public static void main(String[] args) {
Cuoco Mario=new Cuoco();
Apprendista Antonio=new Apprendista();
Mario.Pasta("sugo");
Antonio.Pasta("aglio", "olio");
}
}
run: io cucino pasta con sugo io cucino pasta con aglio e olio BUILD SUCCESSFUL (total time: 0 seconds)
Bene.
Da quando l'Apprendista ha elaborato il suo metodo di cucina con due condimenti non cucina più con un solo condimento: dal momento che i due stanno al ristorante insieme, il maestro Cuoco cucina a un condimento, mentre l'Apprendista Antonio cucina a due condimenti.
Vediamo l'ulteriore evoluzione della cosa...
mercoledì 3 settembre 2014
Scenetta al Ristorante del C#. Sempre il solito apprendista innovatore!
Adesso ripetiamo la stessa storia al Ristorante del C#.
Bene.
Adesso il solito apprendista rompiscatole innovativo si inventa l'idea di cucinare la pasta con due condimenti, come quello del Ristorante del C++...
Quindi quando l'Apprendista è solo al ristorante, e arriva il cliente tradizionalista, lui può accontentarlo anche senza bisogno di ridichiarare il metodo rapportandolo al metodo del maestro Cuoco: il metodo ereditato viene overloadato dal nuovo metodo con lo stesso nome!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("Io cucino pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
}
class Program
{
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
Mario.Pasta("broccoli");
Antonio.Pasta("sugo");
}
}
}
Io cucino pasta con broccoli Io cucino pasta con sugo
Bene.
Adesso il solito apprendista rompiscatole innovativo si inventa l'idea di cucinare la pasta con due condimenti, come quello del Ristorante del C++...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Cuoco
{
public void Pasta(string condimento)
{
Console.WriteLine("Io cucino pasta con " + condimento);
Console.ReadLine();
}
}
class Apprendista : Cuoco
{
public void Pasta(string condimento, string condimento2)
{
Console.WriteLine("Io cucino la pasta con " + condimento + " e " + condimento2);
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Cuoco Mario = new Cuoco();
Apprendista Antonio = new Apprendista();
Mario.Pasta("broccoli");
Antonio.Pasta("sugo");
Antonio.Pasta("aglio", "olio");
}
}
}
Io cucino pasta con broccoli Io cucino pasta con sugo Io cucino la pasta con aglio e olioEcco: diversamente da quanto avveniva in C++, che in presenza di un altro metodo con lo stesso nome, sia pur con parametri diversi, si annullava il metodo ereditato, qui non si annulla, viene overloadato. E questa è una prima importante differenza (forse la maggiore, prima delle interfacce).
Quindi quando l'Apprendista è solo al ristorante, e arriva il cliente tradizionalista, lui può accontentarlo anche senza bisogno di ridichiarare il metodo rapportandolo al metodo del maestro Cuoco: il metodo ereditato viene overloadato dal nuovo metodo con lo stesso nome!
martedì 2 settembre 2014
Metodi virtuali in C#
Per le funzioni virtuali in C# non sono necessari i puntatori.
A parte questo, non basta dichiarare virtual un metodo nella classe base, ma si deve trovare anche una corrispondenza del metodo con lo stesso nome nella classe derivata dichiarandolo override, altrimenti l'istanza della classe derivata attribuita a una variabile di tipo classe base esegue il metodo della classe base.
Adesso dichiaro virtual un metodo della classe base, dichiarando override il metodo con lo stesso nome nella classe derivata, quindi tolgo l'override e verifico:
Ora tolgo override:
A parte questo, non basta dichiarare virtual un metodo nella classe base, ma si deve trovare anche una corrispondenza del metodo con lo stesso nome nella classe derivata dichiarandolo override, altrimenti l'istanza della classe derivata attribuita a una variabile di tipo classe base esegue il metodo della classe base.
Adesso dichiaro virtual un metodo della classe base, dichiarando override il metodo con lo stesso nome nella classe derivata, quindi tolgo l'override e verifico:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Base
{
public virtual void metodo()
{
Console.WriteLine("Io sono il metodo della classe Base");
Console.ReadLine();
}
}
class Derivata:Base{
public override void metodo()
{
Console.WriteLine("Io ridefinisco il metodo della classe Base");
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Base miaBase=new Base();
Derivata miaDerivata=new Derivata();
Base x;
x = miaDerivata;
miaBase.metodo();
miaDerivata.metodo();
x.metodo();
}
}
}
Io sono il metodo della classe Base Io ridefinisco il metodo della classe Base Io ridefinisco il metodo della classe Base
Ora tolgo override:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Base
{
public virtual void metodo()
{
Console.WriteLine("Io sono il metodo della classe Base");
Console.ReadLine();
}
}
class Derivata:Base{
public void metodo()
{
Console.WriteLine("Io ridefinisco il metodo della classe Base");
Console.ReadLine();
}
}
class Program
{
static void Main(string[] args)
{
Base miaBase=new Base();
Derivata miaDerivata=new Derivata();
Base x;
x = miaDerivata;
miaBase.metodo();
miaDerivata.metodo();
x.metodo();
}
}
}
Io sono il metodo della classe Base Io ridefinisco il metodo della classe Base Io sono il metodo della classe BaseEcco: perfettamente dimostrato!
Iscriviti a:
Post (Atom)
