44. Local variables and anonymous delegates

בפעמים האחרונות ראינו קצת מה זה Anonymous delegates, והבנו גם למה זה טוב.

אחד הדברים המגניבים בAnonymous delegates זה שהם יכולים להשתמש במשתנים המקומיים של הפונקציה בה מוגדר הdelegate האנונימי.

למשל, אם נמשיך עם הדוגמה של אתמול, יש לנו סדרה של מספרים שלמים:

1
public delegate int Sequence(int n);

נוכל ליצור פונקציה שיוצרת סדרה חשבונית:

1
2
3
4
5
6
7
public static Sequence CreateArithmeticSequence(int first, int difference)
{
return delegate(int n)
{
return (first + difference*(n - 1));
};
}

שימו לב שהdelegate שלנו ניגש לפרמטרי הפונקציה ומשתמש בהם.

למשל אם נשתמש בזה:

1
2
3
4
5
6
7
8
Sequence oddNumbers = CreateArithmeticSequence(1, 2);
for (int i = 1; i <= 10; i++)
{
Console.Write(oddNumbers(i) + ",");
}
// 1,3,5,7,9,11,13,15,17,19

אבל אתם עשויים לחשוב שהdelegate האנונימי יכול לגשת אולי רק לפרמטרים של הפונקציה.

אז זהו שלא – ניצור באופן שקול פונקציה כזאת

1
2
3
4
5
6
7
8
9
public static Sequence CreateArithmeticSequence(int first, int second)
{
int difference = second - first;
return delegate(int n)
{
return (first + difference*(n - 1));
};
}

וגם זה יתקמפל ויעבוד:

1
2
3
4
5
6
Sequence oddNumbers = CreateArithmeticSequence(1, 3);
for (int i = 1; i <= 10; i++)
{
Console.Write(oddNumbers(i) + ",");
}

איך זה עובד?

מבט חטוף בReflector מראה שהקומפיילר החכם מג’נרט את הקוד הבא, בתור מחלקה פנימית:

(שיניתי את השמות כדי שיהיה אפשר לקרוא אותו קצת)

1
2
3
4
5
6
7
8
9
10
11
12
13
[CompilerGenerated]
private sealed class SequenceInfo
{
// Fields
public int difference;
public int first;
// Methods
public int CreateArithmeticSequence(int n)
{
return (this.first + (this.difference * (n - 1)));
}
}

ולמשל בדוגמה השנייה שראינו הקוד מקומפל למשהו כזה:

1
2
3
4
5
6
7
8
9
10
11
public static Sequence CreateArithmeticSequence(int first, int second)
{
int difference = second - first;
SequenceInfo sequenceInfo = new SequenceInfo();
sequenceInfo.first = first;
sequenceInfo.difference = difference;
return sequenceInfo.CreateArithmeticSequence;
}

מגניב, לא?

המשך שבוע אנונימי טוב

שתף