none
יצירת אוסף מותאם אישית עם שימוש בHashtable (VB.NET) RRS feed

  • שאלה

  • המטרה שלי היא ליצור סוג אוסף חדש בעזרת "overloads item" שבHashtable. אני רוצה לפנות לאוסף עצמו בעזרת מחרוזת שם, ובכך לעדכן את הערכים הקיימים או לשלוף אותם. הסתכלו בשגרות של הכפתורים למטה (btn_ReadPersonValue, btn_EditPersonValue)

    דוגמא נוספת היא " TreeView1.Nodes(2).Text"

    במקרה הזה אפשר לפנות אל Node שהאינדקס שלו הוא 2, ולשנות את ערך הטקסט או לחלופין לקרוא אותו. אני מעוניין ליצור משהו דומה לכך, שעל ידי כתיבה אינדקס (בין אם זה מספר או מחרזות) אוכל לשלוף את הערך, ובמידה הצורך לעדכן/לקרוא אותו.

    Public Class Form1
    
        Private ppl As New People 
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim Prsn As New Person With {.Age = 23, .Children = 3, .Job = "Fishman"} 
            ppl.Add("Michael", Prsn)
    
        End Sub
        Private Sub btn_EditPersonValue_Click(sender As Object, e As EventArgs) Handles btn_EditPersonValue.Click
            ppl.Item("Michael").Job = "Actor" ' עדכון ערך
        End Sub
    
        Private Sub btn_ReadPersonValue_Click(sender As Object, e As EventArgs) Handles btn_ReadPersonValue.Click
            MsgBox(ppl.Item("Michael").Job) ' קריאת ערך
    
        End Sub
    
    
    End Class
    
    
    Public Class People
        Inherits Hashtable
    
        Public Overloads Sub Add(PersonName As String, PersonInfo As Person) 
            MyBase.Add(PersonName, PersonInfo)
        End Sub
    
        Default Public Overloads Property Item(ByVal PersonName As String) As Person
            Get
                Return CType(Me.Item(PersonName), Person)
    
            End Get
            Set(ByVal value As Person)
                Me.Add(Me.Item(PersonName), value)
            End Set
        End Property
    
    
    End Class
    Public Class Person
        Public Property Age As Integer
        Public Property Children As Integer
        Public Property Job As String
    
    
    End Class

    מתי שאני לוחץ על אחד הכפתורים, מופיעה לי השגיאה הבאה: 

     An unhandled exception of type 'System.StackOverflowException' occurred in WindowsApplication1.exe

    תמונה:

    social.msdn.microsoft.com/Forums/getfile/535344

    יום ראשון 21 ספטמבר 2014 00:11

תשובות

  • מצאתי את הבעיה, הפתרון הוא: 

      Default Public Overloads Property Item(PersonName As String) As Person
            Get
                Return MyBase.Item(PersonName)
            End Get
            Set(value As Person)
                MyBase.Item(PersonName) = value
            End Set
        End Property

    שני דברים עיקרים:

    1. בSet valua השתמשתי בADD, מה שלא שמתי לב אליו בהתחלה. אנחנו צריכים לערוך ערך, ולא להוסיף אחד חדש

    2. משום מה התבלבלתי קצת עם ME ועם MYBASE. במקום להתייחס לheshtable התייחסתי למחלקה Person, מה שגרם כמובן לשגיאה.

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 10:08
    יום ראשון 21 ספטמבר 2014 09:27
  • בכיף :-)

    למרות שמצאת את התשובה כדאי להציג לך כמה נקודות שיכולות לעזור:

    * הקדמה! אני כבר כמה שנים טובות לא כתבתי קוד ב VB.NET אז כך הכל בערבון מוגבל מבחינת הקוד (זה פורום C# אחרי הכל). ההבדלים בעקרון הם רק בפורמט של הכתיבה ולא במשמעות (בסופו של דבר הכל מקומפל לאותה שפה CLR).

    >> אתה עשה שימוש לא נכון במושג NODE. התרגום של המילה NODE הוא צומת. מושג זה מתאים לעבודה עם נתונים הכולללים צמתים כמו JSON. באוספים בדרך כלל מדברים על INDEX או KEY שהוא המפתח הייחודי לפיו פונים לאיבר מסוים באוסף. איברים במחלקת Hashtable כוללים על פי ההגדרה, מפתח (KEY) וכמובן את החלק של הערך (VALUE). המפתח יכול להיות שרשרת והערך יכול להיות שרשרת גם כן. מה שמעלה את הנקודה הבאה ->

    >> הקוד שלך לא הגיוני. לשם מה אתה מוסיף אפשרות למתודה ADD אשר כבר קיימת בדיוק בצורה זו? לא יכולות שתי מתודות עם אותו שם ואותם INPUT בדיוק. האפשרות של ADD כבר קיימת במחלקת ה HASH והיא יודעת לקבל שני STRING ואתה למעשה לא עושה שום שינוי.

        Public Overloads Sub Add(PersonName As String, PersonInfo As Person) 
            MyBase.Add(PersonName, PersonInfo)
        End Sub

    מה שהיה יכול להיות הרבה יותר הגיוני זה להוסיף אפשרות של הוספת אובייקט Person למשל משהו כזה

        Public Overloads Sub Add(Person) 
            MyBase.Add(PersonName As String, PersonInfo As Person)
        End Sub

    >> תמיד תבצע הפרדה בין החלק של ה GUI מהחלק של הליבה. בחלק של הליבה יוכל לעזור לך כל מפתח בעקרון, מפני שזה הלוגיקה והבסיס של השפה. החלק של ה GUI שונה ואנשים מתמקצעים באפליקציות מסוגים שונים. תמיד כדאי לשים את החלק של הליבה במיקום שונה מהחלק של ה GUI (למשל תקייה נפרדת או לפחות בקובת נפרד).

    מקוה שזה עוזר:-)


    [Personal Site] [Blog] [Facebook]signature

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 12:42
    יום ראשון 21 ספטמבר 2014 10:48
    מנחה דיון
  • הנה מימוש קצר של הרעיונות שאתה מבצע בשפת C# עם כמה הערות. שים לב למתודה המיותר ITEM ולמימוש של המתודה ADD, אצלי ולהערות בכלל,

    namespace QQ
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			People P = new People();
    
    			Person Per1 = new Person();
    			Per1.Age = 10;
    			Per1.Children = 1;
    			Per1.Job = "fgsfdgsdfgsd";
    			Per1.Name = "A";
    			P.Add(Per1);
    			Console.WriteLine(P.ToString(Per1));
    
    			Person Per2 = new Person();
    			Per2.Age = 10;
    			Per2.Children = 1;
    			Per2.Job = "fgsfdgsdfgsd";
    			Per2.Name = "B";
    			P.Add(Per2);
    			Console.WriteLine(P.ToString(Per2));
    
    			Console.WriteLine(P.Values.Count);
    
    			Console.WriteLine(P.ToString());
    
    			Console.WriteLine(P.item("A").Name);
    			// item methode is not needed since we have build in selection uing the key. Like this:
    			Console.WriteLine( ((Person)P["A"]).Name);
    
    			Console.ReadKey();
    		}
    	}
    }
    
    public class Person
    {
    	public int Age { get; set; }
    	public int Children { get; set; }
    	public String Job { get; set; }
    	public String Name { get; set; }
    }
    
    public class People : Hashtable
    {
    
    	public Person item(String _S)
    	{
    		return (Person)this[_S];
    	}
    
    	public void Add(Person Per)
    	{
    		this.Add(Per.Name, Per);
    	}
    
    	// This is overloading for the methode ToString.
    	// This mean we add an option of using oString with input type Person
    	public String ToString(Person P)
    	{
    		return (String.Format("Name:{3}, Age: {0}, Children: {1}, Job: {2}", P.Age, P.Children, P.Job, P.Name));
    	}
    
    	public override string ToString()
    	{
    		StringBuilder SB = new StringBuilder();
    		foreach (Person Per in this.Values)
    		{
    			SB.Append(String.Format("Name:{3}, Age: {0}, Children: {1}, Job: {2} \n", Per.Age, Per.Children, Per.Job, Per.Name));
    		}
    		return (String)SB.ToString();
    	}
    	//public override 
    }


    [Personal Site] [Blog] [Facebook]signature

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 12:42
    יום ראשון 21 ספטמבר 2014 11:01
    מנחה דיון

כל התגובות

  • מצאתי את הבעיה, הפתרון הוא: 

      Default Public Overloads Property Item(PersonName As String) As Person
            Get
                Return MyBase.Item(PersonName)
            End Get
            Set(value As Person)
                MyBase.Item(PersonName) = value
            End Set
        End Property

    שני דברים עיקרים:

    1. בSet valua השתמשתי בADD, מה שלא שמתי לב אליו בהתחלה. אנחנו צריכים לערוך ערך, ולא להוסיף אחד חדש

    2. משום מה התבלבלתי קצת עם ME ועם MYBASE. במקום להתייחס לheshtable התייחסתי למחלקה Person, מה שגרם כמובן לשגיאה.

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 10:08
    יום ראשון 21 ספטמבר 2014 09:27
  • בכיף :-)

    למרות שמצאת את התשובה כדאי להציג לך כמה נקודות שיכולות לעזור:

    * הקדמה! אני כבר כמה שנים טובות לא כתבתי קוד ב VB.NET אז כך הכל בערבון מוגבל מבחינת הקוד (זה פורום C# אחרי הכל). ההבדלים בעקרון הם רק בפורמט של הכתיבה ולא במשמעות (בסופו של דבר הכל מקומפל לאותה שפה CLR).

    >> אתה עשה שימוש לא נכון במושג NODE. התרגום של המילה NODE הוא צומת. מושג זה מתאים לעבודה עם נתונים הכולללים צמתים כמו JSON. באוספים בדרך כלל מדברים על INDEX או KEY שהוא המפתח הייחודי לפיו פונים לאיבר מסוים באוסף. איברים במחלקת Hashtable כוללים על פי ההגדרה, מפתח (KEY) וכמובן את החלק של הערך (VALUE). המפתח יכול להיות שרשרת והערך יכול להיות שרשרת גם כן. מה שמעלה את הנקודה הבאה ->

    >> הקוד שלך לא הגיוני. לשם מה אתה מוסיף אפשרות למתודה ADD אשר כבר קיימת בדיוק בצורה זו? לא יכולות שתי מתודות עם אותו שם ואותם INPUT בדיוק. האפשרות של ADD כבר קיימת במחלקת ה HASH והיא יודעת לקבל שני STRING ואתה למעשה לא עושה שום שינוי.

        Public Overloads Sub Add(PersonName As String, PersonInfo As Person) 
            MyBase.Add(PersonName, PersonInfo)
        End Sub

    מה שהיה יכול להיות הרבה יותר הגיוני זה להוסיף אפשרות של הוספת אובייקט Person למשל משהו כזה

        Public Overloads Sub Add(Person) 
            MyBase.Add(PersonName As String, PersonInfo As Person)
        End Sub

    >> תמיד תבצע הפרדה בין החלק של ה GUI מהחלק של הליבה. בחלק של הליבה יוכל לעזור לך כל מפתח בעקרון, מפני שזה הלוגיקה והבסיס של השפה. החלק של ה GUI שונה ואנשים מתמקצעים באפליקציות מסוגים שונים. תמיד כדאי לשים את החלק של הליבה במיקום שונה מהחלק של ה GUI (למשל תקייה נפרדת או לפחות בקובת נפרד).

    מקוה שזה עוזר:-)


    [Personal Site] [Blog] [Facebook]signature

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 12:42
    יום ראשון 21 ספטמבר 2014 10:48
    מנחה דיון
  • הנה מימוש קצר של הרעיונות שאתה מבצע בשפת C# עם כמה הערות. שים לב למתודה המיותר ITEM ולמימוש של המתודה ADD, אצלי ולהערות בכלל,

    namespace QQ
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			People P = new People();
    
    			Person Per1 = new Person();
    			Per1.Age = 10;
    			Per1.Children = 1;
    			Per1.Job = "fgsfdgsdfgsd";
    			Per1.Name = "A";
    			P.Add(Per1);
    			Console.WriteLine(P.ToString(Per1));
    
    			Person Per2 = new Person();
    			Per2.Age = 10;
    			Per2.Children = 1;
    			Per2.Job = "fgsfdgsdfgsd";
    			Per2.Name = "B";
    			P.Add(Per2);
    			Console.WriteLine(P.ToString(Per2));
    
    			Console.WriteLine(P.Values.Count);
    
    			Console.WriteLine(P.ToString());
    
    			Console.WriteLine(P.item("A").Name);
    			// item methode is not needed since we have build in selection uing the key. Like this:
    			Console.WriteLine( ((Person)P["A"]).Name);
    
    			Console.ReadKey();
    		}
    	}
    }
    
    public class Person
    {
    	public int Age { get; set; }
    	public int Children { get; set; }
    	public String Job { get; set; }
    	public String Name { get; set; }
    }
    
    public class People : Hashtable
    {
    
    	public Person item(String _S)
    	{
    		return (Person)this[_S];
    	}
    
    	public void Add(Person Per)
    	{
    		this.Add(Per.Name, Per);
    	}
    
    	// This is overloading for the methode ToString.
    	// This mean we add an option of using oString with input type Person
    	public String ToString(Person P)
    	{
    		return (String.Format("Name:{3}, Age: {0}, Children: {1}, Job: {2}", P.Age, P.Children, P.Job, P.Name));
    	}
    
    	public override string ToString()
    	{
    		StringBuilder SB = new StringBuilder();
    		foreach (Person Per in this.Values)
    		{
    			SB.Append(String.Format("Name:{3}, Age: {0}, Children: {1}, Job: {2} \n", Per.Age, Per.Children, Per.Job, Per.Name));
    		}
    		return (String)SB.ToString();
    	}
    	//public override 
    }


    [Personal Site] [Blog] [Facebook]signature

    • סומן כתשובה על-ידי DaniAl5 יום ראשון 21 ספטמבר 2014 12:42
    יום ראשון 21 ספטמבר 2014 11:01
    מנחה דיון
  • הבנתי, תודה רבה. רק מבחינת הפן הרעיוני, מה הבדל בין איך שאתה מימשת את המתודה item לאיך שאני מימשתי זאת?
    יום ראשון 21 ספטמבר 2014 12:42
  • אצלך עשית שימוש במאפיין PROPERTIES ואני עשיתי שימוש במתודה. אלו אלמנטים שונים לחלוטין, למרות שלפעמים אפשר לממש רעיון בעזרת שניהם. תנסה להבין מה ההבל בין מאפיין למתודה (פונקציה בשפת העם, פרוצדורה בשפת VB).

    * שים לב לאופן השמוש השונה בשימוש במתודה ובשימוש במאפיין למשל.
    * במקרה הנוכחי זה לא מתאים כמאפיין לדעתי.


    [Personal Site] [Blog] [Facebook]signature

    יום ראשון 21 ספטמבר 2014 12:50
    מנחה דיון