Lecture No. 10
Dated: 21-05-2025
Anonymous Methods
- Declare a
delegate
- Write a
method
with a signature defined by thedelegate
interface - Declare the
event
based on thatdelegate
- Write code to hook the
handler method
up to thedelegate
(this method is theanonymous method
which is amethod
without a name)
using System;
using System.Windows.Forms;
public partial class Form1 : Form {
public Form1() {
InitializeComponent(); // This line is typically present in a partial class for designer-generated code.
// If you're writing a simple example from scratch without the designer, you might omit it.
Button btnHello = new Button();
btnHello.Text = "Hello";
btnHello.Click += delegate { // Anonymous function starts with delegate keyword
MessageBox.Show("Hello");
};
Button btnGoodbye = new Button();
btnGoodbye.Text = "Goodbye";
btnGoodbye.Left = btnHello.Width + 5; // Position it next to the first button
btnGoodbye.Click += delegate(object sender, EventArgs e) { // Anonymous functions with parameters
// Cast sender to Button to get its Text property
string message = (sender as Button).Text;
MessageBox.Show(message);
};
// Add the buttons to the form's controls collection
Controls.Add(btnHello);
Controls.Add(btnGoodbye);
}
// This is typically generated by the designer.
// If you are creating a simple self-contained example for demonstration,
// you might not need to explicitly implement it, but it's good practice.
private void InitializeComponent() {
this.SuspendLayout();
//
// Form1
//
this.ClientSize = new System.Drawing.Size(300, 200); // Set a default size for the form
this.Name = "Form1";
this.Text = "Button Delegates Demo"; // Set a title for the form
this.ResumeLayout(false);
}
// The Main method is usually in Program.cs for Windows Forms applications.
// This is just for a self-contained example.
[STAThread] // Important for Windows Forms applications
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
Nullable Values
We can create nullable value
types by appending a question mark
to a type name
.
using System;
class NullableTypesDemo {
static void Main(string[] args) {
// Declare a nullable integer and initialize it
int? unitsInStock = 5;
// Declare a nullable DateTime
DateTime? startDate;
// Initialize startDate to the current date and time
startDate = DateTime.Now;
Console.WriteLine($"Start Date (initialized): {startDate}");
// Set startDate to null
startDate = null;
Console.WriteLine($"Start Date (set to null): {startDate}"); // This will print an empty line or "null"
// Demonstrating conditional assignment for nullable types
int availableUnits;
// Option 1: Using an if-else statement
if (unitsInStock == null) {
availableUnits = 0;
}
else {
// Explicit cast is required to convert from nullable int? to non-nullable int
availableUnits = (int)unitsInStock;
}
Console.WriteLine($"Available Units (using if-else): {availableUnits}");
// Option 2: Using the null-coalescing operator (??) - a more concise way
int availableUnitsConcise = unitsInStock ?? 0;
Console.WriteLine($"Available Units (using ?? operator): {availableUnitsConcise}");
// Example with another nullable int set to null
int? quantity = null;
int displayQuantity = quantity ?? -1; // If quantity is null, displayQuantity will be -1
Console.WriteLine($"Display Quantity (with null quantity): {displayQuantity}");
Console.ReadLine(); // Keep the console window open
}
}
Debugging in Visual Studio
Conditional breakpoints
have a hit count
and when hit
condition.
Pressing F5
stops execution at breakpoints.
XML
Stands for "Extended Markup Language"; is a stricter version of HTML
and is used for exchanging data.
<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2012-12-18">
<Cube currency="USD" rate="1.3178"/>
<Cube currency="JPY" rate="110.53"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="25.200"/>
<Cube currency="DKK" rate="7.4603"/>
<Cube currency="GBP" rate="0.81280"/>
<Cube currency="HUF" rate="288.40"/>
<Cube currency="LTL" rate="3.4528"/>
<Cube currency="LVL" rate="0.6961"/>
<Cube currency="PLN" rate="4.0928"/>
<Cube currency="RON" rate="4.4700"/>
<Cube currency="SEK" rate="8.7378"/>
<Cube currency="CHF" rate="1.2080"/>
<Cube currency="NOK" rate="7.3850"/>
<Cube currency="HRK" rate="7.5380"/>
<Cube currency="RUB" rate="40.6850"/>
<Cube currency="TRY" rate="2.3476"/>
<Cube currency="AUD" rate="1.2512"/>
<Cube currency="BRL" rate="2.7595"/>
<Cube currency="CAD" rate="1.2972"/>
<Cube currency="CNY" rate="8.2079"/>
<Cube currency="HKD" rate="10.2131"/>
<Cube currency="IDR" rate="12707.71"/>
<Cube currency="ILS" rate="4.9615"/>
<Cube currency="INR" rate="72.2880"/>
<Cube currency="KRW" rate="1413.30"/>
<Cube currency="MXN" rate="16.7795"/>
<Cube currency="MYR" rate="4.0236"/>
<Cube currency="NZD" rate="1.5660"/>
<Cube currency="PHP" rate="54.068"/>
<Cube currency="SGD" rate="1.6053"/>
<Cube currency="THB" rate="40.285"/>
<Cube currency="ZAR" rate="11.2733"/>
</Cube>
</Cube>
</gesmes:Envelope>
There are 2 methods to read XML
documents.
XmlDocument
Loads the whole document in memory, lets you go backward and forward and even apply XPath
searches on it.
using System;
using System.Xml; // Required for XmlDocument and XmlNode
namespace ParsingXml {
class Program {
static void Main(string[] args) {
// Create a new XmlDocument instance
XmlDocument xmlDoc = new XmlDocument();
try {
// Load the XML document from the specified URL
xmlDoc.Load("http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml");
// Navigate to the specific nodes containing currency rates.
// Based on the XML structure, this path targets the <Cube> elements within the
// <Cube time="..."> element.
// xmldoc.documentelement -> <gesmes:Envelope> (root)
// .childnodes[2] -> <Cube> (the one containing time-stamped cubes)
// .childnodes[0] -> <Cube time="2012-12-18"> (the first child of the above Cube)
// .ChildNodes -> Collection of individual <Cube currency="..."> elements
foreach (XmlNode xmlNode in xmlDoc.DocumentElement.ChildNodes[2].ChildNodes[0].ChildNodes) {
// Check if the node is an element and has the expected attributes
if (xmlNode.NodeType == XmlNodeType.Element &&
xmlNode.Attributes["currency"] != null &&
xmlNode.Attributes["rate"] != null) {
// Access the "currency" and "rate" attributes and print their values
Console.WriteLine(xmlNode.Attributes["currency"].Value + ": " + xmlNode.Attributes["rate"].Value);
}
}
}
catch (XmlException ex) {
Console.WriteLine($"XML Error: {ex.Message}");
}
catch (Exception ex) {
Console.WriteLine($"An error occurred: {ex.Message}");
}
Console.ReadKey(); // Keep the console window open until a key is pressed
}
}
}
XmlReader
This takes less memory and reads one element at a time.
using System;
using System.Text;
using System.Xml;
namespace ParsingXml {
class Program {
static void Main(string[] args) {
// The URL for the ECB daily exchange rates XML feed
string xmlUrl = "http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml";
// Create an XmlReader instance to read the XML from the URL
XmlReader xmlReader = XmlReader.Create(xmlUrl);
// Loop through the XML file node by node
while (xmlReader.Read()) {
// Check if the current node is an element and its name is "Cube"
if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "Cube")) {
// Check if the "Cube" element has attributes
if (xmlReader.HasAttributes) {
// The innermost "Cube" elements have "currency" and "rate" attributes
// The outer "Cube" element might have a "time" attribute.
// We are interested in the ones with "currency" and "rate".
string currency = xmlReader.GetAttribute("currency");
string rate = xmlReader.GetAttribute("rate");
if (currency != null && rate != null) {
Console.WriteLine($"{currency}: {rate}");
}
}
}
}
Console.ReadKey(); // Keep the console window open until a key is pressed
}
}
}
An xmlnode
is derived from xmlelement
and contains
Name
innertext
innerxml
outerxml
attributes
1
XPath
is a cross platform XML Query Language
.
Examples
With XmlNode.SelectSingleNode()
using System;
using System.Text;
using System.Xml; // Required for XmlDocument and XmlNode
namespace ParsingXml {
class Program {
static void Main(string[] args) {
XmlDocument xmlDoc = new XmlDocument();
try {
// Load the XML document from the specified RSS feed URL
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
// Select a single node using an XPath expression
// This XPath targets the 'title' element that is a child of 'channel', which is a child of 'rss'.
XmlNode titleNode = xmlDoc.SelectSingleNode("//rss/channel/title");
// Check if the title node was found before trying to access its InnerText
if (titleNode != null) {
Console.WriteLine(titleNode.InnerText);
}
else {
Console.WriteLine("Title node not found.");
}
}
catch (XmlException ex) {
Console.WriteLine($"XML Error: {ex.Message}");
}
catch (Exception ex) {
Console.WriteLine($"An error occurred: {ex.Message}");
}
Console.ReadKey(); // Keep the console window open until a key is pressed
}
}
}
With XmlNode.SelectNodes()
using System;
using System.Text;
using System.Xml; // Required for XmlDocument and XmlNode
namespace ParsingXml {
class Program {
static void Main(string[] args) {
XmlDocument xmlDoc = new XmlDocument();
try {
// Load the XML document from the specified RSS feed URL
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
// Select all 'item' nodes that are children of 'channel' which is a child of 'rss'.
XmlNodeList itemNodes = xmlDoc.SelectNodes("//rss/channel/item");
// Iterate through each 'item' node found
foreach (XmlNode itemNode in itemNodes) {
// Within each 'item' node, select the single 'title' child node
XmlNode titleNode = itemNode.SelectSingleNode("title");
// Within each 'item' node, select the single 'pubDate' child node
XmlNode dateNode = itemNode.SelectSingleNode("pubDate");
// Check if both title and date nodes were found
if ((titleNode != null) && (dateNode != null)) {
// Print the publication date and the title of the news item
Console.WriteLine(dateNode.InnerText + ": " + titleNode.InnerText);
}
}
}
catch (XmlException ex) {
Console.WriteLine($"XML Error: {ex.Message}");
}
catch (Exception ex) {
Console.WriteLine($"An error occurred: {ex.Message}");
}
Console.ReadKey(); // Keep the console window open until a key is pressed
}
}
}
Writing XML
Using XmlWriter
using System;
using System.Text;
using System.Xml; // Required for XmlWriter
namespace WritingXml {
class Program {
static void Main(string[] args) {
// Create an XmlWriter instance to write to "test.xml"
// XmlWriter.Create provides options for formatting (indentation, encoding).
// Here, we're using default settings, which often means no indentation.
// For indented output, you might use:
// XmlWriterSettings settings = new XmlWriterSettings { Indent = true, IndentChars = " " };
// XmlWriter xmlWriter = XmlWriter.Create("test.xml", settings);
XmlWriter xmlWriter = XmlWriter.Create("test.xml");
// Start the XML document
xmlWriter.WriteStartDocument();
// Write the root element <users>
xmlWriter.WriteStartElement("users");
// Write the first <user> element
xmlWriter.WriteStartElement("user");
xmlWriter.WriteAttributeString("age", "42"); // Add an attribute to <user>
xmlWriter.WriteString("John Doe"); // Add inner text to <user>
xmlWriter.WriteEndElement(); // Close the <user> element
// Write the second <user> element
xmlWriter.WriteStartElement("user");
xmlWriter.WriteAttributeString("age", "39"); // Add an attribute to <user>
xmlWriter.WriteString("Jane Doe"); // Add inner text to <user>
xmlWriter.WriteEndElement(); // Close the <user> element
// End the XML document (this automatically closes any open elements, including <users>)
xmlWriter.WriteEndDocument();
// Close the XmlWriter to ensure all buffered data is written to the file
xmlWriter.Close();
Console.WriteLine("XML file 'test.xml' created successfully.");
Console.ReadKey(); // Keep the console window open
}
}
}
The above code creates the following XML
.
<users>
<user age="42">John Doe</user>
<user age="39">Jane Doe</user>
</users>
References
-
Read more about attributes. ↩