/*
Questo esempio implementa una collezione Orders di coppie (OrderNumber, Order).
La classe Orders è ottenuta derivando da DictionaryBase. Alla classe comunque
sono stati aggiunti i metodi Strong-Typed oltre a quelli ereditati da DictionaryBase
ed implementati esplicitamente sulle interfaccie IDictionary, ICollection e IEnumerable.
*/
using sys = System;
using sysCols = System.Collections;
//
//-----------------------------------------------------------------------------------------------
// Key: Number
//-----------------------------------------------------------------------------------------------
//
public struct OrderNumber
{
private static int globalNum = 1000;
public int Year;
public int Number;
public void SetNewOrderNumber()
{
Year =sys.DateTime.Now.Year;
Number = ++globalNum;
}
public override int GetHashCode()
{
return sys.String.Format("{0}-{1}", Year, Number).GetHashCode();
}
public override string ToString()
{
return sys.String.Format("{0}-{1}", Year, Number);
}
}
//
//-----------------------------------------------------------------------------------------------
// Item: Order
//-----------------------------------------------------------------------------------------------
//
public class Order {
private OrderNumber num;
private string customer = "?";
public Order() {
num = new OrderNumber();
num.SetNewOrderNumber();
}
public Order(OrderNumber number) {num = number;}
public string Customer {
get {return customer;}
set {customer = value;}
}
public OrderNumber Number {
get {return num;}
}
public override string ToString() {
return sys.String.Format("[{0} {1}]", num, customer);
}
}
//
//-----------------------------------------------------------------------------------------------
// Collection: Orders
//-----------------------------------------------------------------------------------------------
//
public class Orders : sysCols.DictionaryBase {
//////////////////////////////////////////////////////////////////////////////////
// FOUNDATION MEMBERS
//////////////////////////////////////////////////////////////////////////////////
// Default Constructor
public Orders() {}
// Copy-Constructor
public Orders(Orders value)
{
foreach(sysCols.DictionaryEntry myPair in value.Dictionary)
this.Dictionary.Add(myPair.Key, myPair.Value);
}
//////////////////////////////////////////////////////////////////////////////////
// MODIFIERS MEMBERS
//////////////////////////////////////////////////////////////////////////////////
// Type-safe version of IDictionary.Item
public Order this[OrderNumber index]
{
get {return ((Order)(this.Dictionary[index]));}
set {this.Dictionary[index] = value;}
}
// Type-safe version of IDictionary.Add
public void Add(OrderNumber key, Order value) {this.Dictionary.Add(key, value);}
// Type-safe version of IDictionary.Remove
public void Remove(OrderNumber key) {this.Dictionary.Remove(key);}
//////////////////////////////////////////////////////////////////////////////////
// ACCESSOR MEMBERS
//////////////////////////////////////////////////////////////////////////////////
// Type-safe version of IDictionary.Contains
public bool Contains(OrderNumber key) {return this.Dictionary.Contains(key);}
// Type-safe version of IEnumerable.GetEnumerator
public new Orders.DictionaryEnumerator GetEnumerator() {return new Orders.DictionaryEnumerator(this);}
// Type-safe version of ICollection.CopyTo
public void CopyTo(Orders.DictionaryEntry[] array, int index) {
sysCols.DictionaryEntry[] tmp = new sysCols.DictionaryEntry[array.Length-index];
this.Dictionary.CopyTo(tmp, index);
for(int i = 0; i < tmp.Length; ++i) {
if (object.ReferenceEquals(tmp[i].Key, null)) break;
array[index + i] = new Orders.DictionaryEntry((OrderNumber)tmp[i].Key, (Order)tmp[i].Value);
}
}
// Type-safe version of IDictionary.Keys
// public sysCols.ICollection Keys {
// get {
// sysCols.IDictionary tmpDict = this;
// sysCols.ICollection tmpKeys = tmpDict.Keys;
// OrderNumberCollection[] tmpOnKeys; <- Implementare una collezione (da ReadOnlyCollectionBase) di OrderNumber strong-typed
// tmpKeys.CopyTo(tmpOnKeys, 0);
// return tmpOnKeys;
// }
// }
// Type-safe version of IDictionary.Values
// public sysCols.ICollection Values {
// get {
// sysCols.IDictionary tmpDict = this;
// sysCols.ICollection tmpVals = tmpDict.Values;
// OrderCollection tmpOrdVals; <- Implementare una collezione (da ReadOnlyCollectionBase) di Order strong-typed
// tmpVals.CopyTo(tmpOrdVals, 0);
// return tmpOrdVals;
// }
// }
//////////////////////////////////////////////////////////////////////////////////
// EVENTS & DELEGATES
//////////////////////////////////////////////////////////////////////////////////
protected override void OnValidate(object key, object value)
{
if((key == null || key is OrderNumber) && (value == null || value is Order))
return;
throw new sys.ArgumentException("Sono permessi solo coppie di tipo (OrderNumber, Order).");
}
//////////////////////////////////////////////////////////////////////////////////
// NESTED ITERATOR & C.
//////////////////////////////////////////////////////////////////////////////////
public struct DictionaryEntry{
private OrderNumber kk;
private Order vv;
// Constructor
public DictionaryEntry(OrderNumber key, Order value){
kk = key;
vv = value;
}
// Properties
public OrderNumber Key {
get {return kk;}
set {kk = value;}
}
public Order Value {
get {return vv;}
set {vv = value;}
}
// Methods
public override string ToString() {
return sys.String.Format("{0} -> {1}", kk, vv);
}
// Conversions
//public static implicit operator DictionaryEntry(sysCols.DictionaryEntry de) {
// return new DictionaryEntry((OrderNumber)de.Key, (Order)de.Value);
//}
}
public class DictionaryEnumerator: sysCols.IDictionaryEnumerator
{
private sysCols.IDictionaryEnumerator baseEnumerator;
// CONSTRUCTOR
public DictionaryEnumerator(Orders mapping) {
sysCols.DictionaryBase tmp = mapping;
this.baseEnumerator = tmp.GetEnumerator();
}
// ACCESSOR METHODS
// Type-unsafe explicit interface implementation of IDictionaryEnumerator.Entry
sysCols.DictionaryEntry sysCols.IDictionaryEnumerator.Entry {
get{return this.baseEnumerator.Entry;}
}
// Type-safe DictionaryEnumerator Entry
DictionaryEntry Entry {
get{
return new DictionaryEntry(Key, Value);
}
}
// Type-unsafe explicit interface implementation of IDictionaryEnumerator.Key
object sysCols.IDictionaryEnumerator.Key {get{return this.baseEnumerator.Key;}}
// Type-safe DictionaryEnumerator Key
OrderNumber Key {get{return (OrderNumber)this.baseEnumerator.Key;}}
// Type-unsafe explicit interface implementation of IDictionaryEnumerator.Value
object sysCols.IDictionaryEnumerator.Value {get{return this.baseEnumerator.Value;}}
// Type-safe DictionaryEnumerator Value
Order Value {get{return (Order)this.baseEnumerator.Value;}}
// Type-safe iterator Current method
public DictionaryEntry Current {
get {return Entry;}
}
// Type-unsafe IEnumerator.Current
object sysCols.IEnumerator.Current {
get {return baseEnumerator.Current;}
}
// Type-unsafe IEnumerator.MoveNext()
bool sysCols.IEnumerator.MoveNext() {return baseEnumerator.MoveNext();}
// Type-safe iterator MoveNext() method
public bool MoveNext() {return baseEnumerator.MoveNext();}
// Type-unsafe IEnumerator.Reset()
void sysCols.IEnumerator.Reset() {baseEnumerator.Reset();}
// Type-safe iterator Reset() method
public void Reset() {baseEnumerator.Reset();}
}
}
//
//-----------------------------------------------------------------------------------------------
// Main App
//-----------------------------------------------------------------------------------------------
//
class MainApp{
public static void Main(){
//
// Esercito i costruttori tipizzati
//
Orders myOrders;
{
Orders tmpOrders = new Orders();
for(int i = 0; i<10; ++i)
{
Order o = new Order();
tmpOrders.Add(o.Number, o);
}
myOrders = new Orders(tmpOrders);
}
{
Orders myTmpOrders = new Orders(myOrders);
// error CS1502: The best overloaded method match for 'Orders.Orders(Orders)' has some invalid arguments
// Scommenta la linea di codice per verificare che il costruttore tipizzato funziona
//Orders myTmpOrders2 = new Orders(new object());
}
//
// Esercito l'enumeratore tipizzato
//
foreach(Orders.DictionaryEntry numOrdPair in myOrders)
{
OrderNumber tmpOn = numOrdPair.Key;
Order tmpOrd = numOrdPair.Value;
// error CS0029: Cannot implicitly convert type 'OrderNumber' to 'string'
// Scommenta le linee di codice per verificare che l'Entry tipizzato funziona
//string tmpK = numOrdPair.Key;
//string tmpV = numOrdPair.Value;
sys.Console.WriteLine("Entry Key: {0} \t\t Value: {1}", numOrdPair.Key, numOrdPair.Value);
}
// error CS0030: Cannot convert type 'Orders.DictionaryEntry' to 'string'
// Scommenta la linea di codice per verificare che l'enumeratore tipizzato funziona
//foreach(string numOrdPair in myOrders) {sys.Console.WriteLine(numOrdPair);}
// Scommenta per verificare che l'enumeratore non tipizzato implementato esplicitamenete
// sull'interfaccia IEnumerable funziona sempre.
//foreach(sysCols.DictionaryEntry numOrdPair in (sysCols.IEnumerable)myOrders) {sys.Console.WriteLine(numOrdPair);}
//
// Esercito i metodi tipizzati
//
{
Order tmpOrd = new Order();
myOrders[tmpOrd.Number] = tmpOrd;
// error CS0029: Cannot implicitly convert type 'object' to 'Order'
// Scommenta la linea di codice per verificare che il metodo tipizzato funziona
//myOrders[tmpOrd.Number] = new object();
}
{
Order tmpOrd = new Order();
myOrders.Add(tmpOrd.Number, tmpOrd);
}
// error CS1502: The best overloaded method match for 'Orders.Add(OrderNumber, Order)' has some invalid arguments
// Scommenta la linea di codice per verificare che il metodo tipizzato funziona
//myOrders.Add(new object(), new object());
{
Order tmpOrd = new Order();
myOrders.Add(tmpOrd.Number, tmpOrd);
myOrders.Remove(tmpOrd.Number);
// error CS1502: The best overloaded method match for 'Orders.Remove(OrderNumber)' has some invalid arguments
// Scommenta la linea di codice per verificare che il metodo tipizzato funziona
//myOrders.Remove(new object());
sys.Console.WriteLine("Contains {0}: {1}",tmpOrd.Number ,myOrders.Contains(tmpOrd.Number));
}
// error CS1502: The best overloaded method match for 'Orders.Contains(OrderNumber)' has some invalid arguments
// Scommenta la linea di codice per verificare che il metodo tipizzato funziona
//myOrders.Contains(new object());
{
myOrders[new OrderNumber()] = null;
Orders.DictionaryEntry[] vetPair = new Orders.DictionaryEntry[20];
myOrders.CopyTo(vetPair, 0);
sys.Console.WriteLine(vetPair.Length);
}
{
string[] vetOrd = new string[20];
// error CS1502: The best overloaded method match for 'Orders.Contains(OrderNumber)' has some invalid arguments
// Scommenta la linea di codice per verificare che il metodo tipizzato funziona
//myOrders.CopyTo(vetOrd, 0);
}
//
// Esercito i metodi non tipizzati
//
sysCols.IDictionary aDict = myOrders;
{
Order tmpOrd = new Order();
aDict[tmpOrd.Number] = tmpOrd;
// Scommenta la linea di codice per verificare che l'evento OnValidate intercetta
// l'errore solo Run-Time
//aDict[tmpOrd.Number] = new object();
}
{
Order tmpOrd = new Order();
aDict.Add(tmpOrd.Number, tmpOrd);
}
// Scommenta la linea di codice per verificare che l'evento OnValidate intercetta
// l'errore solo a Run-Time
//aDict(123, "Arbracadabra")
{
Order tmpOrd = new Order();
aDict.Add(tmpOrd.Number, tmpOrd);
object tmpObj = tmpOrd.Number;
aDict.Remove(tmpObj);
}
// Scommenta la linea di codice per verificare che l'evento OnValidate intercetta
// l'errore solo a Run-Time
//aDict.Remove(new object());
return;
}
}
/*
SMemorandum:
Descrizione dei metodi usati per implementare (i) la tipizzazione forte a partire da
quanto ereditato (e) dalla classe base DirectoryBase:
- (i) Orders.this[] strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.this[] di DictionaryBase implemetato esplicitamente sull'interfaccia
- (i) Add(...) strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.Add() di DictionaryBase implemetato esplicitamente sull'interfaccia
- (i) Remove(...) strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.Remove() di DictionaryBase implemetato esplicitamente sull'interfaccia
- (i) Contains(...) strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.Contains() di DictionaryBase implemetato esplicitamente sull'interfaccia
- (i) Orders.GetEnumerator() strong-typed fa l'hide col modifier new (non può fare l'Overloading
perché non ha parametri, non può fare l'Override perché il tipo di ritorno è diverso e c'è
già una copia (e) sull'interfaccia principale)
- (i) CopyTo(...) strong-typed in Overload sull'interfaccia della classe (e) perchè ha parametri
diversi
- (i) Keys strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.Keys() di DictionaryBase implementato esplicitamente sull'interfaccia
- (i) Values(...) strong-typed sull'interfaccia della classe;
(e) Orders.IDictionary.Values() di DictionaryBase implemetato esplicitamente sull'interfaccia
*/