using …

Pure C#

‘Delegate’ Kategorisi için Arşiv

Handling and Raising Events

Yazan: esersahin 23/03/2009

http://msdn.microsoft.com/en-us/library/edzehd2t(VS.80).aspx

Events in the .NET Framework are based on the delegate model. (Those familiar with design patterns in object-oriented programming will notice the observer design pattern.) This section contains topics that describe the delegate model, show how to consume events in applications, and describe how to raise events from your class.

For details about the event syntax in a specific programming language, see the documentation for that language.

In This Section

Events and Delegates
Provides an overview of the event model and describes delegates in the .NET Framework.

How to: Connect Event Handler Methods to Events
Shows how to define an event handler and add it to an event raised in another class.

Consuming Events
Provides an overview of how .NET Framework applications consume events.

How to: Consume Events in a Web Forms Application
Shows how to handle an event raised by a Web Forms control.

How to: Consume Events in a Windows Forms Application
Shows how to handle an event raised by a Windows Form control.

Raising an Event
Explains how to provide event functionality in your class.

How to: Implement Events in Your Class
Shows how to define and raise an event in your class.

How to: Raise and Consume Events
Contains a detailed sample that raises an event in one class and handles the event in another class.

Raising Multiple Events
Describes a technique for optimizing storage for multiple events.

How to: Handle Multiple Events with Event Properties
Shows how to use event properties for handling multiple events.

Related Sections

ASP.NET Web Server Control Event Model
Describes the details of the event model for ASP.NET Web Forms.

Creating Event Handlers in Windows Forms
Describes the details of the event model for Windows Forms.

Server Event Handling in ASP.NET Web Pages
Describes how to raise events from custom ASP.NET server controls.

Events in Visual Basic
Describes how to define, raise, and handle events in Visual Basic.

Events in Windows Forms Controls
Describes how to raise events from custom Windows Forms controls.

Managed and Unmanaged Events
Describes how managed events in the .NET Framework interoperate with unmanaged COM events.

Yazı kategorisi: Asp.Net, Delegate, User Control | » yorum bırak;

ASP.NET 101 – Part 2: Sending event data in your custom events

Yazan: esersahin 23/03/2009

http://mats.softgear.se/post/ASPNET-101-ndash3b-Part-2-Sending-event-data-in-your-custom-events.aspx

One of the key benefits of encapsulating logic and behavior in a user control is that the user of the control doesn’t have to care about the inner workings of the control. We only need to expose the things that the users of the control needs.

We will demonstrate this by creating a simple user registration control. The control will expose an event, UserCreated, which will contain the newly created user as data.

This way the page that the user control is located in doesn’t need to care about what fields the user needs to fill out or how the person is created. It is simply handed a user that was created.

We’ll start by looking at our sample user control.

PersonEntryControl.ascx

   1: <%@ Control Language="C#" AutoEventWireup="true"
   2: CodeBehind="PersonEntryControl.ascx.cs" Inherits="PersonEntryControl" %>

   3: First name: <br />
   4: <asp:TextBox runat="server" ID="FirstNameTextBox" /> <br />
   5: Last name: <br />
   6: <asp:TextBox runat="server" ID="LastNameTextBox" /> <br />
   7: Email: <br />
   8: <asp:TextBox runat="server" ID="EmailTextBox" /> <br />
   9: <asp:Button runat="server" ID="AddButton" Text="Add"
  10:     onclick="AddButton_Click" />

PersonEntryControl.ascx.cs

   1: using System;
   2: namespace UserControl_Event_2
   3: {
   4:     public partial class PersonEntryControl : System.Web.UI.UserControl
   5:     {
   6:         protected void AddButton_Click(object sender, EventArgs e)
   7:         {
   8:             Person newPerson = new Person()
   9:             {
  10:                 FirstName = FirstNameTextBox.Text,
  11:                 LastName = LastNameTextBox.Text,
  12:                 Email = EmailTextBox.Text
  13:             };
  14:             OnPersonCreated(new GenericEventArgs<Person>(newPerson));
  15:         }
  16:         public event EventHandler<GenericEventArgs<Person>> PersonCreated;
  17:         protected void OnPersonCreated(GenericEventArgs<Person> e)
  18:         {
  19:             if (PersonCreated != null)
  20:             {
  21:                 PersonCreated(this, e);
  22:             }
  23:         }
  24:     }
  25: }

As you can see the user control contains a button and three textboxes for first name, last name and email address.

When we click the button we create a new person and then trigger the event. If you look at the event declaration you can see that it differs from the previous example.

public event EventHandler<GenericEventArgs<Person>> PersonCreated;

We are now using a generic version of the EventHandler that allows us to specify what type the EventArgs parameter should be. Here I have created a generic EventArgs class that allows us to send any data structure along with our event.

Here is what the GenericEventArgs<T> class looks like:

GenericEventArgs.cs

   1: using System;
   2:  namespace UserControl_Event_2
   3: {
   4:     public class GenericEventArgs<T> : EventArgs
   5:     {
   6:         public T Data { get; set; }
   7:         public GenericEventArgs(T data)
   8:         {
   9:             Data = data;
  10:         }
  11:     }
  12: }

The most important thing about it is that it inherits from EventArgs, this is what allows us to use it with our event.

Now when we trigger the event from the user control we can send along the created person with the line:

OnPersonCreated(new GenericEventArgs<Person>(newPerson));

Now let’s create a page where we can try out the user control.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
 Inherits="UserControl_Event_2._Default" %>

<%@ Register src="PersonEntryControl.ascx" tagname="PersonEntryControl"
tagprefix="uc1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <uc1:PersonEntryControl ID="PersonEntryControl1" runat="server"
              OnPersonCreated="PersonEntryControl1_PersonCreated" />
    </div>
    <div>
        <asp:Label runat="server" ID="StatusLabel" />
    </div>
    </form>
</body>
</html>

Default.aspx.cs

using System;
namespace UserControl_Event_2
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void PersonEntryControl1_PersonCreated(object sender,
                            GenericEventArgs<Person> e)
        {
            StatusLabel.Text = string.Format("Created person: {0} {1}",
                e.Data.FirstName, e.Data.LastName);
        }
    }
}

As you can see in the event handler we can easily access the person with e.Data.

Download the sample and play around with it, a nice exercise is to add some validation to the user control and maybe add some more fields to the person.

UserControl Event 2.zip (21,22 kb)

Yazı kategorisi: Asp.Net, Delegate, User Control | » yorum bırak;

ASP.NET 101 – Part 1: Communication from User control to Page in ASP.NET

Yazan: esersahin 23/03/2009

http://mats.softgear.se/post/ASPNET-101—Part-1-Communication-from-User-control-to-Page-in-ASPNET.aspx

User controls are great for encapsulating both behavior and look. When you have some UI elements that you want to use in more than one place a User control is a great way to add reusability.

One problem that you can run into is how you add communication from the user control to the web page. Perhaps you have a button in a user control, and when you click it the web page should perform some action. If the button was on the page we would simply bind to the Clicked event on the button, but when it’s inside of the user control we don’t have access to the button.

Luckily it is really easy in .NET to add your own events. In this really simple example we will create a user control with a button that also has an event, ButtonClicked. We will then create a page that contains an instance of the user control and bind to the exposed event so that the page will know when the button has been clicked.

We begin with the user control:

EventControl.ascx

   1: <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="EventControl.ascx.cs"
   2: Inherits="UserControl_Event_1.EventControl" %>

   3: <asp:Button runat="server" ID="ClickButton" Text="Click me!"
   4:     onclick="ClickButton_Click" />

EventControl.ascx.cs

   1: using System;
   2: namespace UserControl_Event_1
   3: {
   4:     public partial class EventControl : System.Web.UI.UserControl
   5:     {
   6:         protected void ClickButton_Click(object sender, EventArgs e)
   7:         {
   8:             OnButtonClicked(EventArgs.Empty);
   9:         }
  10:         protected void OnButtonClicked(EventArgs e)
  11:         {
  12:             if (ButtonClicked != null)
  13:             {
  14:                 ButtonClicked(this, e);
  15:             }
  16:         }
  17:         public event EventHandler ButtonClicked;
  18:     }
  19: }

The markup doesn’t contain anything special, just a button where we’ve bound to the click event.

The code-behind file contains our event that is exposed:

public event EventHandler ButtonClicked;

When we want to trigger this event we use the method OnButtonClicked:

protected void OnButtonClicked(EventArgs e)
{
    if (ButtonClicked != null)
    {
        ButtonClicked(this, e);
    }
}

If no one has bound to the event ButtonClicked will be null so we need to check that before we trigger it.

It is common to use the naming convention used here. The event says what has happened, like Clicked. And the method we use to trigger the event is called On<Event name>, like OnClicked.

So in our click event for the button we trigger the event with the line:

OnButtonClicked(EventArgs.Empty);

In this example we won’t send any data along with the event so we can use the predefined event argument EventArgs.Empty.

You can also note that when we trigger the event we send along the object that triggered it, the first parameter to the event this. That way the page can check exactly which user control that triggered it by checking the sender argument in the event handler.

We will now create a page that will use our simple user control.

Default.aspx

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
   2:  Inherits="UserControl_Event_1._Default" %>

   3: <%@ Register src="EventControl.ascx" tagname="EventControl" tagprefix="uc1" %>
   4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   5: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   6: <html xmlns="http://www.w3.org/1999/xhtml" >
   7: <head runat="server">
   8:     <title>Untitled Page</title>
   9: </head>
  10: <body>
  11:     <form id="form1" runat="server">
  12:     <div>
  13:         <uc1:EventControl ID="EventControl1" runat="server" OnButtonClicked="EventControl1_ButtonClicked" />
  14:         <br />
  15:         <asp:Label runat="server" ID="MessageLabel" />
  16:     </div>
  17:     </form>
  18: </body>
  19: </html>

Default.aspx.cs

   1: using System;
   2: using System.Web.UI;
   3: namespace UserControl_Event_1
   4: {
   5:     public partial class _Default : System.Web.UI.Page
   6:     {
   7:         protected void EventControl1_ButtonClicked(object sender, EventArgs e)
   8:         {
   9:             MessageLabel.Text = "You clicked it! " + DateTime.Now.ToLongTimeString();
  10:         }
  11:     }
  12: }

You can see in Default.aspx that intellisense of our user control contains our new event. Note that the event is called On<Event name> when it is used in markup, if you look in the code behind you can see that the event really is called ButtonClicked.

We create an event handler for the event and perform some action, updating a label with a message and the time so we see that something has happened.

You can recreate the sample or download the attached .zip-file containing a complete solution. This was a real quick example, next time I’ll extend this concept and show how to send data along with the event.

UserControl Event 1.zip (18,09 kb)

Yazı kategorisi: Asp.Net, Delegate, User Control | » yorum bırak;

Adding an Event to a User Control (Code Sample)

Yazan: esersahin 23/03/2009

http://timstall.dotnetdevelopersjournal.com/adding_an_event_to_a_user_control.htm

I had talked about how to trigger an event from a UserControl.

This ability has many benefits, such as with refactoring. For example, suppose a UserControl is hosted on many different pages, and each page requires that the control have slightly different validation that incorporates values from the host page. One way to do this is to have the UserControl call a validation method on the host page.

Here’s a code snippet you can download that shows how to have a UC call a method on its parent. The idea is to add an event member to the control, and hook it up with a delegate. (I had initially seen this technique from an article on MSDN several years ago).

This specific example has four files:

  • A UserControl – RecordNav.ascx and RecordNav.ascx.cs
  • A host page – HostRecordNav.aspx and HostRecordNav.aspx.cs

Yazı kategorisi: Asp.Net, Delegate, User Control | » yorum bırak;

Create Elegant Code with Anonymous Methods, Iterators, and Partial Classes

Yazan: esersahin 20/10/2008

http://msdn.microsoft.com/en-us/magazine/cc163970.aspx

his article was based on a pre-release version of Microsoft Visual Studio 2005, formerly code-named “Whidbey.” All information contained herein is subject to change.

This article discusses:

  • Iterating over collections
  • Spanning class definitions across files
  • Anonymous methods for use with delegates
  • Other new C# features in Visual Studio 2005
This article uses the following technologies:
C# and Visual Studio
Fans of the C# language will find much to like in Visual C#® 2005. Visual Studio® 2005 brings a wealth of exciting new features to Visual C# 2005, such as generics, iterators, partial classes, and anonymous methods. While generics is the most talked-about and anticipated feature, especially among C++ developers who are familiar with templates, the other new features are important additions to your Microsoft® .NET development arsenal as well. These features and language additions will improve your overall productivity compared to the first version of C#, leaving you to write cleaner code faster. For some background information on generics, you should take a look at the sidebar “What are Generics?”
Iterators
In C# 1.1, you can iterate over data structures such as arrays and collections using a foreach loop:

string[] cities = {"New York","Paris","London"};
foreach(string city in cities)
{
   Console.WriteLine(city);
}
In fact, you can use any custom data collection in the foreach loop, as long as that collection type implements a GetEnumerator method that returns an IEnumerator interface. Usually you do this by implementing the IEnumerable interface:

public interface IEnumerable
{
   IEnumerator GetEnumerator();
}
public interface IEnumerator
{
   object Current{get;}
   bool MoveNext();
   void Reset();
}
Often, the class that is used to iterate over a collection by implementing IEnumerable is provided as a nested class of the collection type to be iterated. This iterator type maintains the state of the iteration. A nested class is often better as an enumerator because it has access to all the private members of its containing class. This is, of course, the Iterator design pattern, which shields iterating clients from the actual implementation details of the underlying data structure, enabling the use of the same client-side iteration logic over multiple data structures, as shown in Figure 1.

Figure 1 Iterator Design Pattern
In addition, because each iterator maintains separate iteration state, multiple clients can execute separate concurrent iterations. Data structures such as the Array and the Queue support iteration out of the box by implementing IEnumerable. The code generated in the foreach loop simply obtains an IEnumerator object by calling the class’s GetEnumerator method and uses it in a while loop to iterate over the collection by continually calling its MoveNext method and current property. You can use IEnumerator directly (without resorting to a foreach statement) if you need explicit iteration over the collection.
But there are some problems with this approach. The first is that if the collection contains value types, obtaining the items requires boxing and unboxing them because IEnumerator.Current returns an Object. This results in potential performance degradation and increased pressure on the managed heap. Even if the collection contains reference types, you still incur the penalty of the down-casting from Object. While unfamiliar to most developers, in C# 1.0 you can actually implement the iterator pattern for each loop without implementing IEnumerator or IEnumerable. The compiler will choose to call the strongly typed version, avoiding the casting and boxing. The result is that even in version 1.0 it’s possible not to incur the performance penalty.
To better formulate this solution and to make it easier to implement, the Microsoft .NET Framework 2.0 defines the generic, type-safe IEnumerable<ItemType> and IEnumerator<ItemType> interfaces in the System.Collections.Generics namespace:

public interface IEnumerable<ItemType>
{
   IEnumerator<ItemType> GetEnumerator();
}
public interface IEnumerator<ItemType> : IDisposable
{
   ItemType Current{get;}
   bool MoveNext();
}
Besides making use of generics, the new interfaces are slightly different than their predecessors. Unlike IEnumerator, IEnumerator<ItemType> derives from IDisposable and does not have a Reset method. The code in Figure 2 shows a simple city collection implementing IEnumerable<string>, and Figure 3 shows how the compiler uses that interface when spanning the code of the foreach loop. The implementation in Figure 2 uses a nested class called MyEnumerator, which accepts as a construction parameter a reference back to the collection to be enumerated. MyEnumerator is intimately aware of the implementation details of the city collection, an array in this example. The MyEnumerator class maintains the current iteration state in the m_Current member variable, which is used as an index into the array.
The second and more difficult problem is implementing the iterator. Although that implementation is straightforward for simple cases (as shown in Figure 3), it is challenging with more advanced data structures, such as binary trees, which require recursive traversal and maintaining iteration state through the recursion. Moreover, if you require various iteration options, such as head-to-tail and tail-to-head on a linked list, the code for the linked list will be bloated with various iterator implementations. This is exactly the problem that C# 2.0 iterators were designed to address. Using iterators, you can have the C# compiler generate the implementation of IEnumerator for you. The C# compiler can automatically generate a nested class to maintain the iteration state. You can use iterators on a generic collection or on a type-specific collection. All you need to do is tell the compiler what to yield in each iteration. As with manually providing an iterator, you need to expose a GetEnumerator method, typically by implementing IEnumerable or IEnumerable<ItemType>.
You tell the compiler what to yield using the new C# yield return statement. For example, here is how you use C# iterators in the city collection instead of the manual implementation of Figure 2:

public class CityCollection : IEnumerable<string>
{
   string[] m_Cities = {"New York","Paris","London"};
   public IEnumerator<string> GetEnumerator()
   {
      for(int i = 0; i<m_Cities.Length; i++)
         yield return m_Cities[i];
   }
}

You can also use C# iterators on non-generic collections:

public class CityCollection : IEnumerable
{
   string[] m_Cities = {"New York","Paris","London"};
   public IEnumerator GetEnumerator()
   {
      for(int i = 0; i<m_Cities.Length; i++)
         yield return m_Cities[i];
   }
}
In addition, you can use C# iterators on fully generic collections, as shown in Figure 4. When using a generic collection and iterators, the specific type used for IEnumerable<ItemType> in the foreach loop is known to the compiler from the type used when declaring the collection—a string in this case:

LinkedList<int,string> list = new LinkedList<int,string>();
/* Some initialization of list, then  */
foreach(string item in list)
{
   Trace.WriteLine(item);
}

This is similar to any other derivation from a generic interface.

If for some reason you want to stop the iteration midstream, use the yield break statement. For example, the following iterator will only yield the values 1, 2, and 3:

public IEnumerator<int> GetEnumerator()
{
   for(int i = 1;i< 5;i++)
   {
      yield return i;
      if(i > 2)
         yield break;
   }
}
Your collection can easily expose multiple iterators, each used to traverse the collection differently. For example, to traverse the CityCollection class in reverse order, provide a property of type IEnumerable<string> called Reverse:

public class CityCollection
{
   string[] m_Cities = {"New York","Paris","London"};
   public IEnumerable<string> Reverse
   {
      get
      {
         for(int i=m_Cities.Length-1; i>= 0; i--)
            yield return m_Cities[i];
      }
   }
}

Then use the Reverse property in a foreach loop:

CityCollection collection = new CityCollection();
foreach(string city in collection.Reverse)
{
   Trace.WriteLine(city);
}
There are some limitations to where and how you can use the yield return statement. A method or a property that has a yield return statement cannot also contain a return statement because that would improperly break the iteration. You cannot use yield return in an anonymous method, nor can you place a yield return statement inside a try statement with a catch block (and also not inside a catch or a finally block).
Iterator Implementation
The compiler-generated nested class maintains the iteration state. When the iterator is first called in a foreach loop (or in direct iteration code), the compiler-generated code for GetEnumerator creates a new iterator object (an instance of the nested class) with a reset state. Every time the foreach loops and calls the iterator’s MoveNext method, it begins execution where the previous yield return statement left off. As long as the foreach loop executes, the iterator maintains its state. However, the iterator object (and its state) does not persist across foreach loops. Consequently, it is safe to call foreach again because you will get a new iterator object to start the new iteration. This is why IEnumerable<ItemType> does not define a Reset method.
But how is the nested iterator class implemented and how does it manage its state? The compiler transforms a standard method into a method that is designed to be called multiple times and that uses a simple state machine to resume execution after the previous yield statement. All you have to do is indicate what and when to yield to the compiler using the yield return statement. The compiler is even smart enough to concatenate multiple yield return statements in the order they appear:

public class CityCollection : IEnumerable<string>
{
   public IEnumerator<string> GetEnumerator()
   {
      yield return "New York";
      yield return "Paris";
      yield return "London";
   }
}
Let’s take a look at the GetEnumerator method of the class shown in the following lines of code:

public class MyCollection : IEnumerable<string>
{
   public IEnumerator<string> GetEnumerator()
   {
      //Some iteration code that uses yield return
   }
}

When the compiler encounters a class member with a yield return statement such as this, it injects the definition of a nested class called GetEnumerator$<random unique number>__IEnumeratorImpl, as shown in the C# pseudocode in Figure 5. (Remember that all of the features discussed in this article—the names of the compiler-generated classes and fields—are subject to change, in some cases quite drastically. You should not attempt to use reflection to get at those implementation details and expect consistent results.)

The nested class implements the same IEnumerable interface returned from the class member. The compiler replaces the code in the class member with an instantiation of the nested type, assigning to the nested class’s <this> member variable a reference back to the collection, similar to the manual implementation shown in Figure 2. The nested class is actually the one providing the implementation of IEnumerator.
Recursive Iterations
Iterators really shine when it comes to iterating recursively over a data structure such as a binary tree or any complex graph of interconnecting nodes. With recursive iteration, it is very difficult to manually implement an iterator, yet using C# iterators it is done with great ease. Consider the binary tree in Figure 6. The full implementation of the tree is part of the source code available with this article.
The binary tree stores items in nodes. Each node holds a value of the generic type T, called Item. Each node has a reference to a node on the left and a reference to a node on the right. Values smaller than Item are stored in the left-side subtree, and larger values are stored in the right-side subtree. The tree also provides an Add method for adding an open-ended array of values of the type T, using the params qualifier:

public void Add(params T[] items);
The tree provides a public property called InOrder of type IEnumerable<T>. InOrder calls the recursive private helper method ScanInOrder, passing to ScanInOrder the root of the tree. ScanInOrder is defined as:

IEnumerable<T> ScanInOrder(Node<T> root);

It returns the implementation of an iterator of the type IEnumerable<T>, which traverses the binary tree in order. The interesting thing about ScanInOrder is the way it uses recursion to iterate over the tree using a foreach loop that accesses the IEnumerable<T> returned from a recursive call. With in-order iteration, every node iterates over its left-side subtree, then over the value in the node itself, then over the right-side subtree. For that, you need three yield return statements. To iterate over the left-side subtree, ScanInOrder uses a foreach loop over the IEnumerable<T> returned from a recursive call that passes the left-side node as a parameter. Once that foreach loop returns, all the left-side subtree nodes have been iterated over and yielded. ScanInOrder then yields the value of the node passed to it as the root of the iteration and performs another recursive call inside a foreach loop, this time on the right-side subtree.

The InOrder property allows you to write the following foreach loop to iterate over the entire tree:

BinaryTree<int> tree = new BinaryTree<int>();
tree.Add(4,6,2,7,5,3,1);
foreach(int num in tree.InOrder)
{
   Trace.WriteLine(num);
}
// Traces 1,2,3,4,5,6,7

You can implement pre-order and post-order iterations in a similar manner by adding additional properties.

While the ability to use iterators recursively is obviously a powerful feature, it should be used with care as there can be serious performance implications. Each call to ScanInOrder requires an instantiation of the compiler-generated iterator, so recursively iterating over a deep tree could result in a large number of objects being created behind the scenes. In a balanced binary tree, there are approximately n iterator instantiations, where n is the number of nodes in the tree. At any given moment, approximately log(n) of those objects are live. In a decently sized tree, a large number of those objects will make it past the Generation 0 garbage collection. That said, iterators can still be used to easily iterate over recursive data structures such as trees by using stacks or queues to maintain a list of nodes still to be examined.
Partial Types
C# 1.1 requires you to put all the code for a class in a single file. C# 2.0 allows you to split the definition and implementation of a class or a struct across multiple files. You can put one part of a class in one file and another part of the class in a different file, noting the split by using the new partial keyword. For example, you can put the following code in the file MyClass1.cs:

public partial class MyClass
{
   public void Method1()
   {...}
}

In the file MyClass2.cs, you can insert this code:

public partial class MyClass
{
   public void Method2()
   {...}
   public int Number;
}
In fact, you can have as many parts as you like in any given class. Partial type support is available for classes, structures, and interfaces, but you cannot have a partial enum definition.
Partial types are a very handy feature. Sometimes it is necessary to modify a machine-generated file, such as a Web service client-side wrapper class. However, changes made to the file will be lost if you regenerate the wrapper class. Using a partial class, you can factor those changes into a separate file. ASP.NET 2.0 uses partial classes for the code-beside class (the evolution of codebehind), storing the machine-generated part of the page separately. Windows® Forms uses partial classes to store the visual designer output of the InitializeComponent method as well as the member controls. Partial types also enable two or more developers to work on the same type while both have their files checked out from source control without interfering with each other.
You may be asking yourself, what if the various parts define contradicting aspects of the class? The answer is simple: a class (or a struct) can have two kinds of aspects or qualities: accumulative and non-accumulative. The accumulative aspects are things that each part of the class can choose to add, such as interface derivation, properties, indexers, methods, and member variables.
For example, the following code shows how a part can add interface derivation and implementation:

public partial class MyClass
{}
public partial class MyClass : IMyInterface
{
   public void Method1()
   {...}
   public void Method2()
   {...}
}
The non-accumulative aspects are things that all the parts of a type must agree upon. Whether the type is a class or a struct, type visibility (public or internal) and the base class are non-accumulative aspects. For example, the following code does not compile because not all the parts of MyClass concur on the base class:

public class MyBase
{}
public class SomeOtherClass
{}
public partial class MyClass : MyBase
{}
public partial class MyClass : MyBase
{}
//Does not compile
public partial class MyClass : SomeOtherClass
{}

In addition to having all parts define the same non-accumulative parts, only a single part can override a virtual or an abstract method, and only one part can implement an interface member.

C# 2.0 supports partial types as follows: when the compiler builds the assembly, it combines from the various files the parts of a type and compiles them into a single type in Microsoft intermediate language (MSIL). The generated MSIL has no recollection which part came from which file. Just like in C# 1.1 the MSIL has no record of which file was used to define which type. Also worth noting is that partial types cannot span assemblies, and that a type can refuse to have other parts by omitting the partial qualifier from its definition.
Because all the compiler is doing is accumulating parts, a single file can contain multiple parts, even of the same type, although the usefulness of that is questionable.
In C#, developers often name a file after the class it contains and avoid putting multiple classes in the same file. When using partial types, I recommend indicating in the file name that it contains parts of a type such as MyClassP1.cs, MyClassP2.cs, or employing some other consistent way of externally indicating the content of the source file. For example, the Windows Forms designer stores its portion of the partial class for the form in Form1.cs to a file named Form1.Designer.cs.
Another side effect of partial types is that when approaching an unfamiliar code base, the parts of the type you maintain could be spread all over the project files. In such cases, my advice is to use the Visual Studio Class View because it displays an accumulative view of all the parts of the type and allows you to navigate through the various parts by clicking on its members. The navigation bar provides this functionality as well.
Anonymous Methods
C# supports delegates for invoking one or multiple methods. Delegates provide operators and methods for adding and removing target methods, and are used extensively throughout the .NET Framework for events, callbacks, asynchronous calls, and multithreading. However, you are sometimes forced to create a class or a method just for the sake of using a delegate. In such cases, there is no need for multiple targets, and the code involved is often relatively short and simple. Anonymous methods is a new feature in C# 2.0 that lets you define an anonymous (that is, nameless) method called by a delegate.
For example, the following is a conventional SomeMethod method definition and delegate invocation:

class SomeClass
{
   delegate void SomeDelegate();
   public void InvokeMethod()
   {
      SomeDelegate del = new SomeDelegate(SomeMethod);
      del();
   }
   void SomeMethod()
   {
      MessageBox.Show("Hello");
   }
}

You can define and implement this with an anonymous method:

class SomeClass
{
   delegate void SomeDelegate();
   public void InvokeMethod()
   {
      SomeDelegate del = delegate()
                         {
                             MessageBox.Show("Hello");
                         };
      del();
   }
}

What are Generics?

Generics allow you to define a type-safe data structure or a utility helper class without committing to the actual data types used. This results in a significant performance boost and higher-quality code because you get to reuse data processing algorithms without duplicating type-specific code. For example, instead of defining a linked list in terms of System.Object, you can define it in generic terms, using generic type parameters:

public class LinkedList<T>
{
   T[] m_Items  =  new T[100];
   public void AddHead(T item)
   {...}
   public T RemoveHead(T item);
   {...}
}
T is a merely a placeholder for the actual type to be used. When the client declares and instantiates the list, it provides the type to use instead of the generic type parameter:

LinkedList<int> list = new LinkedList<int>();
list.AddHead(3);
You can use multiple type parameters, such as K for the list key and T for the underlying data type stored:

   public class LinkedList<K,T>
   {...}
You can define generic interfaces and have the subclass either provide a particular type or you can keep the subclass generic:

   public interface IList<T>
   {...}
   public class NumberList :  IList<int>
   {...}
   public class LinkedList<T> :  IList<T>
   {...}
For additional information about generics, see Jason Clark’s .NET columns in the September 2003 and October 2003 issues of MSDN® Magazine. There is also an MSDN whitepaper, “An Introduction to C# Generics,” available.
The anonymous method is defined in-line and not as a member method of any class. Additionally, there is no way to apply method attributes to an anonymous method, nor can the anonymous method define generic types or add generic constraints.
You should note two interesting things about anonymous methods: the overloaded use of the delegate reserved keyword and the delegate assignment. You will see later on how the compiler implements an anonymous method, but it is quite clear from looking at the code that the compiler has to infer the type of the delegate used, instantiate a new delegate object of the inferred type, wrap the new delegate around the anonymous method, and assign it to the delegate used in the definition of the anonymous method (del in the previous example).
Anonymous methods can be used anywhere that a delegate type is expected. You can pass an anonymous method into any method that accepts the appropriate delegate type as a parameter:

class SomeClass
{
   delegate void SomeDelegate();
   public void SomeMethod()
   {
      InvokeDelegate(delegate(){MessageBox.Show("Hello");});
   }
   void InvokeDelegate(SomeDelegate del)
   {
      del();
   }
}

If you need to pass an anonymous method to a method that accepts an abstract Delegate parameter, such as the following

void InvokeDelegate(Delegate del);

first cast the anonymous method to the specific delegate type.

A concrete and useful example for passing an anonymous method as a parameter is launching a new thread without explicitly defining a ThreadStart delegate or a thread method:

public class MyClass
{
   public void LauchThread()
   {
      Thread workerThread = new Thread(delegate()
                            {
                                MessageBox.Show("Hello");
                            });
      workerThread.Start();
   }
}

In the previous example, the anonymous method serves as the thread method, causing the message box to be displayed from the new thread.

Passing Parameters to Anonymous Methods
When defining an anonymous method with parameters, you define the parameter types and names after the delegate keyword just as if it were a conventional method. The method signature must match the definition of the delegate to which it is assigned. When invoking the delegate, you pass the parameter’s values, just as with a normal delegate invocation:

class SomeClass
{
   delegate void SomeDelegate(string str);
   public void InvokeMethod()
   {
      SomeDelegate del = delegate(string str)
                         {
                             MessageBox.Show(str);
                         };
      del("Hello");
   }
}
If the anonymous method has no parameters, you can use a pair of empty parens after the delegate keyword:

class SomeClass
{
   delegate void SomeDelegate();
   public void InvokeMethod()
   {
      SomeDelegate del = delegate()
                         {
                             MessageBox.Show("Hello");
                         };
      del();
   }
}

However, if you omit the empty parens after the delegate keyword altogether, you are defining a special kind of anonymous method, which could be assigned to any delegate with any signature:

class SomeClass
{
   delegate void SomeDelegate(string str);
   public void InvokeMethod()
   {
      SomeDelegate del = delegate
                         {
                             MessageBox.Show("Hello");
                         };
      del("Parameter is ignored");
   }
}
Obviously, you can only use this syntax if the anonymous method does not rely on any of the parameters, and you would want to use the method code regardless of the delegate signature. Note that you must still provide arguments when invoking the delegate because the compiler generates nameless parameters for the anonymous method, inferred from the delegate signature, as if you wrote the following (in C# pseudocode):

SomeDelegate del = delegate(string)
                   {
                       MessageBox.Show("Hello");
                   };

Additionally, anonymous methods without a parameter list cannot be used with delegates that specify out parameters.

An anonymous method can use any class member variable, and it can also use any local variable defined at the scope of its containing method as if it were its own local variable. This is demonstrated in Figure 7. Once you know how to pass parameters to an anonymous method, you can also easily define anonymous event handling, as shown in Figure 8.
Because the += operator merely concatenates the internal invocation list of one delegate to another, you can use the += to add an anonymous method. Note that with anonymous event handling, you cannot remove the event handling method using the -= operator unless the anonymous method was added as a handler by first storing it to a delegate and then registering that delegate with the event. In that case, the -= operator can be used with the same delegate to unregister the anonymous method as a handler.
Anonymous Method Implementation
The code the compiler generates for anonymous methods largely depends on which type of parameters or variables the anonymous methods uses. For example, does the anonymous method use the local variables of its containing method (called outer variables), or does it use class member variables and method arguments? In each case, the compiler will generate different MSIL. If the anonymous method does not use outer variables (that is, it only uses its own arguments or the class members) then the compiler adds a private method to the class, giving the method a unique name. The name of that method will have the following format:

<return type> __AnonymousMethod$<random unique number>(<params>)

As with other compiler-generated members, this is subject to change and most likely will before the final release. The method signature will be that of the delegate to which it is assigned.

The compiler simply converts the anonymous method definition and assignment into a normal instantiation of the inferred delegate type, wrapping the machine-generated private method:

SomeDelegate del = new SomeDelegate(__AnonymousMethod$00000000);

Interestingly enough, the machine-generated private method does not show up in IntelliSense®, nor can you call it explicitly because the dollar sign in its name is an invalid token for a C# method (but a valid MSIL token).

The more challenging scenario is when the anonymous method uses outer variables. In that case, the compiler adds a private nested class with a unique name in the format of:

__LocalsDisplayClass$<random unique number>

The nested class has a back reference to the containing class called <this>, which is a valid MSIL member variable name. The nested class contains public member variables corresponding to every outer variable that the anonymous method uses. The compiler adds to the nested class definition a public method with a unique name, in the format of:

<return type> __AnonymousMethod$<random unique number>(<params>)
The method signature will be that of the delegate to which it is assigned. The compiler replaces the anonymous method definition with code that creates an instance of the nested class and makes the necessary assignments from the outer variables to that instance’s member variables. Finally, the compiler creates a new delegate object, wrapping the public method of the nested class instance, and calls that delegate to invoke the method. Figure 9 shows in C# pseudocode the compiler-generated code for the anonymous method definition in Figure 7.
Generic Anonymous Methods
An anonymous method can use generic parameter types, just like any other method. It can use generic types defined at the scope of the class, for example:

class SomeClass<T>
{
   delegate void SomeDelegate(T t);
   public void InvokeMethod(T t)
   {
      SomeDelegate del = delegate(T item){...}
      del(t);
   }
}
Because delegates can define generic parameters, an anonymous method can use generic types defined at the delegate level. You can specify the type to use in the method signature, in which case it has to match the specific type of the delegate to which it is assigned:

class SomeClass
{
   delegate void SomeDelegate<T>(T t);
   public void InvokeMethod()
   {
      SomeDelegate<int> del = delegate(int number)
                              {
                                 MessageBox.Show(number.ToString());
                              };
      del(3);
   }
}
Anonymous Method Example
Although at first glance the use of anonymous methods may seem like an alien programming technique, I have found it quite useful because it replaces the need for creating a simple method in cases where only a delegate will suffice. Figure 10 shows a real-life example of the usefulness of anonymous methods—the SafeLabel Windows Forms control.
Windows Forms relies on the underlying Win32® messages. Therefore, it inherits the classic Windows programming requirement that only the thread that created the window can process its messages. Calls on the wrong thread will always trigger an exception under Windows Forms in the .NET Framework 2.0. As a result, when calling a form or a control on a different thread, you must marshal that call to the correct owning thread. Windows Forms has built-in support for solving this predicament by having the Control base class implement the interface ISynchronizeInvoke, defined like the following:

public interface ISynchronizeInvoke
{
   bool InvokeRequired {get;}
   IAsyncResult BeginInvoke(Delegate method,object[] args);
   object EndInvoke(IAsyncResult result);
   object Invoke(Delegate method,object[] args);
}
The Invoke method accepts a delegate targeting a method on the owning thread, and it will marshal the call to that thread from the calling thread. Because you may not always know whether you are actually executing on the correct thread, the InvokeRequired property lets you query to see if calling Invoke is required. The problem is that using ISynchronizeInvoke complicates the programming model significantly, and as a result it is often better to encapsulate the interaction with the ISynchronizeInvoke interface in controls and forms that will automatically use ISynchronizeInvoke as required.
For example, instead of a Label control that exposes a Text property, you can define the SafeLabel control which derives from Label, as shown in Figure 10. SafeLabel overrides its base class Text property. In its get and set, it checks whether Invoke is required. If so, it needs to use a delegate to access the property. That implementation simply calls the base class implementation of the property, but on the correct thread. Because SafeLabel only defines these methods so that they can be called through a delegate, they are good candidates for anonymous methods. SafeLabel passes the delegate, wrapping the anonymous methods to the Invoke method as its safe implementation of the Text property.
Delegate Inference
The C# compiler’s ability to infer from an anonymous method assignment which delegate type to instantiate is an important capability. In fact, it enables yet another C# 2.0 feature called delegate inference. Delegate inference allows you to make a direct assignment of a method name to a delegate variable, without wrapping it first with a delegate object. For example, take a look at the following C# 1.1 code:

class SomeClass
{
   delegate void SomeDelegate();
   public void InvokeMethod()
   {
      SomeDelegate del = new SomeDelegate(SomeMethod);
      del();
   }
   void SomeMethod()
   {...}
}

Instead of the previous snippet, you can now write:

class SomeClass
{
   delegate void SomeDelegate();
   public void InvokeMethod()
   {
      SomeDelegate del = SomeMethod;
      del();
   }
   void SomeMethod()
   {...}
}
When you assign a method name to a delegate, the compiler first infers the delegate’s type. Then the compiler verifies that there is a method by that name and that its signature matches that of the inferred delegate type. Finally, the compiler creates a new object of the inferred delegate type, wrapping the method and assigning it to the delegate. The compiler can only infer the delegate type if that type is a specific delegate type—that is, anything other than the abstract type Delegate. Delegate inference is a very useful feature indeed, resulting in concise, elegant code.
I believe that as a matter of routine in C# 2.0, you will use delegate inference rather than the old method of delegate instantiation. For example, here is how you can launch a new thread without explicitly creating a ThreadStart delegate:

public class MyClass
{
   void ThreadMethod()
   {...}
   public void LauchThread()
   {
      Thread workerThread = new Thread(ThreadMethod);
      workerThread.Start();
   }
}
You can use a double stroke of delegate inference when launching an asynchronous call and providing a completion callback method, as shown in Figure 11. There you first assign the method name to invoke asynchronously into a matching delegate. Then call BeginInvoke, providing the completion callback method name instead of a delegate of type AsyncCallback.
Property and Index Visibility
C# 2.0 allows you to specify different visibility for the get and set accessors of a property or an indexer. For example, it is quite common to want to expose the get as public, but the set as protected. To do so, add the protected visibility qualifier to the set keyword. Similarly, you can define the set method of an indexer as protected, (see Figure 12).
There are a few stipulations when using property visibility. First, the visibility qualifier you apply on the set or the get can only be a stringent subset of the visibility of the property itself. In other words, if the property is public, then you can specify internal, protected, protected internal, or private. If the property visibility is protected, you cannot make the get or the set public. In addition, you can only specify visibility for the get or the set, but not both.
Static Classes
It is quite common to have classes with only static methods or members (static classes). In such cases there is no point in instantiating objects of these classes. For example, the Monitor class or class factories such as the Activator class in the .NET Framework 1.1 are static classes. Under C# 1.1, if you want to prevent developers from instantiating objects of your class you can provide only a private default constructor. Without any public constructors, no one can instantiate objects of your class:

public class MyClassFactory
{
   private MyClassFactory()
   {}
   static public object CreateObject()
   {...}
}
However, it is up to you to enforce the fact that only static members are defined on the class because the C# compiler will still allow you to add instance members, although they could never be used. C# 2.0 adds support for static classes by allowing you to qualify your class as static:

public static class MyClassFactory
{
   static public T CreateObject<T>()
   {...}
}
The C# 2.0 compiler will not allow you to add a non-static member to a static class, and will not allow you to create instances of the static class as if it were an abstract class. In addition, you cannot derive from a static class. It’s as if the compiler adds both abstract and sealed to the static class definition. Note that you can define static classes but not static structures, and you can add a static constructor.
Global Namespace Qualifier
It is possible to have a nested namespace with a name that matches some other global namespace. In such cases, the C# 1.1 compiler will have trouble resolving the namespace reference. Consider the following example:

namespace MyApp
{
   namespace System
   {
      class MyClass
      {
         public void MyMethod()
         {
            System.Diagnostics.Trace.WriteLine("It Works!");
         }
      }
   }
}
In C# 1.1, the call to the Trace class would produce a compilation error (without the global namespace qualifier ::). The reason the error would occur is that when the compiler tries to resolve the reference to the System namespace, it uses the immediate containing scope, which contains the System namespace but not the Diagnostics namespace. C# 2.0 allows you to use the global namespace qualifier :: to indicate to the compiler that it should start its search at the global scope. You can apply the :: qualifier to both namespaces and types, as shown in Figure 13.
Inline Warning
C# 1.1 allows you to disable specific compiler warnings using project settings or by issuing command-line arguments to the compiler. The problem here is that this is a global suppression, and as such suppresses warnings that you still want. C# 2.0 allows you to explicitly suppress and restore compiler warnings using the #pragma warning directive:

// Disable 'field never used' warning
#pragma warning disable 169
public class MyClass
{
   int m_Number;
}
#pragma warning restore 169
Disabling warnings should be generally discouraged in production code. It is intended only for analysis when trying to isolate a problem, or when you lay out the code and would like to get the initial code structure in place without having to polish it up first. In all other cases, avoid suppressing compiler warnings. Note that you cannot programmatically override the project settings, meaning you cannot use the pragma warning directive to restore a warning that is suppressed globally.
Conclusion
The new features in C# 2.0 presented in this article are dedicated solutions, designed to address specific problems while simplifying the overall programming model. If you care about productivity and quality, then you want to have the compiler generate as much of the implementation as possible, reduce repetitive programming tasks, and make the resulting code concise and readable. The new features give you just that, and I believe they are an indication that C# is coming of age, establishing itself as a great tool for the developer who is an expert in .NET.

Yazı kategorisi: Delegate, Find, Generic, List | » yorum bırak;

Delegate-Based APIs

Yazan: esersahin 20/10/2008

http://blogs.msdn.com/kcwalina/archive/2004/06/22/162533.aspx

Generics and Anonymous Methods/Delegates make up a powerful pair that can be used to create elegant query APIs. Here are some that we just added to the .NET Framework’s Collection libraries. I used List<T> to illustrate the APIs but most of those were also added to System.Array.

API Design

Delegates

namespace System {

public delegate void Action<T>(T obj);

public delegate bool Predicate<T>(T obj);

public delegate U Converter<T,U>(T from);

public delegate int Comparison<T>(T x, T y);

}

List<T>

public class List<T> : … {

public int FindIndex(Predicate<T> match);

public int FindIndex(int index, Predicate<T> match);

public int FindIndex(int index, int count, Predicate<T> match);

public int FindLastIndex(Predicate<T> match);

public int FindLastIndex(int index, Predicate<T> match);

public int FindLastIndex(int index, int count, Predicate<T> match);

public List<T> FindAll(Predicate<T> match);

public T Find(Predicate<T> match);

public T FindLast(Predicate match);

public bool Exists(Predicate<T> match);

public bool TrueForAll(Predicate<T> match);

public int RemoveAll(Predicate<T> match);

public void ForEach(Action<T> action);

public void Sort(Comparison<T> comparison);

public List<U> ConvertAll<U>(Converter<T,U> converter);

}

Finding Even Integers in List<T>

List<int> integers = new List<int>();

For(int i=1; i<=10; i++) integers.Add(i);

List<int> even = integers.FindAll(delegate(int i){

return i%2==0;

});

Finding Complex Type in List<T>

public class Order {

public Order(int number, string item) { … }

public int Number { get { return number; } }

public string Item { get { return item; } }

}

List<Order> orders = new List<Order>();

int orderNumber = 10;

Order order = orders.Find(delegate(Order o){

return o.Number==orderNumber;

});

Computing Sum of Integers in List<T>

List<int> integers = new List<int>();

for(int i=1; i<=10; i++) integers.Add(i);

int sum;

integers.ForEach(delegate(int i){ sum+=i; });

Sort Orders in List<T>

List<Order> orders = new List<Order>();

orders.Add(new Order(10,”Milk”));

orders.Add(new Order(5,”Cheese”));

orders.Sort(delegate(Order x, Order y){

return Comparer<int>.Default.Compare(x.Number,y.Number);

});

Convert Orders to Order Numbers

List<Order> orders = new List<Order>();

orders.Add(new Order(10,”Milk”));

orders.Add(new Order(5,”Cheese”));

List<int> numbers = orders.ConvertAll(delegate(Order x){

return o.Number;

});

Yazı kategorisi: Delegate, Find, Generic, List | » yorum bırak;

Find data from a data structure(List, Dictionary) using delegate in c# .Net

Yazan: esersahin 20/10/2008

http://sadi02.wordpress.com/2008/06/23/find-data-from-a-data-structurelist-dictionary-using-delegate-in-c-net/

using System;
using System.Collections.Generic;
using System.Text; 
namespace MyDelegate
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> m_liName=new List<string>();
            m_liName.Add("sadi");
            m_liName.Add("pothik");
            m_liName.Add("shiman");
            m_liName.Add("shuvro");
            m_liName.Add("arif");

            //**************Find a single data
            string sName = m_liName.Find(delegate(string s) { return s.Equals("sadi"); });

            //**************Find multiple data
            List<string> liName1 = m_liName.FindAll(delegate(string s) { return s.Equals("sh"); });

            //*************If contains the data**********
            bool bIsSuccess = m_liName.Contains("sadi"); // output: true
        }
    }
}

Yazı kategorisi: Delegate, Find, Generic, List | » yorum bırak;

Using Delegate with Generic List to find an Item(s)

Yazan: esersahin 20/10/2008

http://www.dotnetspider.com/resources/19256-Using-Delegate-with-Generic-List-find-an.aspx

    public class Employee
    {
        public Employee()
        {

        }
        public Employee(int number, string name)
        {
            this._employeeNo = number;
            this._employeeName = name;
        }
        int _employeeNo;
        string _employeeName;

        public int EmployeeNo
        {
            get { return _employeeNo; }
            set { _employeeNo = value; }
        }

        public string EmployeeName
        {
            get { return _employeeName; }
            set { _employeeName = value; }
        }
    }

I’m createing a collection of Employee object and i will add it to the Generic List as give below.


            List employees = new List();
            employees.Add(new Employee(1, "Venkatarajan"));
            employees.Add(new Employee(2, "Siva"));
            employees.Add(new Employee(3, "Yogananthan"));
            employees.Add(new Employee(4, "Senthilkumaran"));
            employees.Add(new Employee(5, "Gopinath"));

Now will look how the delegate can be used to find a Employee object in this collection.
My Scenario is, i need to find a Employee object whose Employee Number is 1. Then your code should look like

            // Get the Employee detail whose Employee Number is 1
            Employee employee = employees.Find(delegate(Employee emp) { return (emp.EmployeeNo == 1); });
            Console.Write(employee.EmployeeName);
            Console.Write(employee.EmployeeNo);

If you want to find more than one employee based on the condition, then you can use the FIndAll method and you can implement the delegate.
Then your code should look like give below.

            // Get all the Employee Details whose Employee Number is greater than 1
            List allEmployees = employees.FindAll(delegate(Employee emp) { return (emp.EmployeeNo > 1); });
            foreach (Employee emp in allEmployees)
            {
                Console.WriteLine(emp.EmployeeName + " - " + emp.EmployeeNo);
            }

Feel free to post your queries here.

Yazı kategorisi: Delegate, Find, Generic, List | » yorum bırak;

C#, List.Find() and Predicates

Yazan: esersahin 20/10/2008

Because I use this just infrequently enough to have to look it up every time…

I’m a huge (ab)user of the .NET generic collection classes, but I hate cluttering code with foreach() loops every time that I need to find an item in a collection. Enter the Find() method, which takes a predicate and does the work for you so you can keep focusing on the stuff that’s actually interesting:

List<SomeObject> myObjects = new List<SomeObject>();
/* .. load objects up somehow .. */
SomeObject desiredObject =
    myObjects.Find(delegate(SomeObject o) { return o.Id == desiredId; });

Yazı kategorisi: Delegate, Find, Generic, List | » yorum bırak;

Predicate Generic Delegate

Yazan: esersahin 20/10/2008

http://msdn.microsoft.com/en-us/library/bfcke1bz(VS.85).aspx

using System;
using System.Drawing;

public class Example
{
    public static void Main()
    {
        // Create an array of five Point structures.
        Point[] points = { new Point(100, 200),
            new Point(150, 250), new Point(250, 375),
            new Point(275, 395), new Point(295, 450) };

        // To find the first Point structure for which X times Y 
        // is greater than 100000, pass the array and a delegate
        // that represents the ProductGT10 method to the Shared 
        // Find method of the Array class. 
        Point first = Array.Find(points, ProductGT10);

        // Note that you do not need to create the delegate 
        // explicitly, or to specify the type parameter of the 
        // generic method, because the C# compiler has enough
        // context to determine that information for you.

        // Display the first structure found.
        Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);
    }

    // This method implements the test condition for the Find
    // method.
    private static bool ProductGT10(Point p)
    {
        if (p.X * p.Y > 100000)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

/* This code example produces the following output:

Found: X = 275, Y = 395
 */

List<MyClass> list = new List<MyClass>();
... // somehow the list gets filled

MyClass ruleMatch = list.Find(delegate(MyClass myclass) { return myclass.someInt >= 5; });
...
if (list.Exists(delegate(MyClass myclass) {return myclass.otherInt == 0;}))
{
   // one exists, do something
}

//complete console application example

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{

public class MyClass
{
private int _someLameInt = 0;
private int _otherLameInt = 0;

public MyClass(int val)
{
this.someLameInt = val;
}

public int someLameInt
{
get { return this._someLameInt; }
set
{
this._someLameInt = value;
this._otherLameInt = this._someLameInt – 1;
}
}

public int otherLameInt
{
get { return this._otherLameInt; }
}

public override string ToString()
{
return String.Format(“Type:{0}\n{1}:{2}\n{3}:{4}”, this.GetType().FullName, “someLameInt”, this.someLameInt.ToString() , “otherLameInt”, this.otherLameInt.ToString() );
}

}

class Program
{
static void Main( string[] args )
{
List<MyClass> list = new List<MyClass>();

for (int i = 1; i < 12; i++)
{

list.Add(new MyClass(i));
}
MyClass ruleMatch = list.Find(delegate( MyClass myclass ) { return myclass.someLameInt >= 5; });

Console.WriteLine(“Match for 5 found:” + ruleMatch.ToString() + “\n\n”);

if (list.Exists(delegate( MyClass myclass ) { return myclass.otherLameInt == 0; }))
{

Console.WriteLine(“otherInt with zero value found.\n\n”);

}

Console.Write(“Type ENTER to exit”);
Console.ReadKey();
}
}

}

Yazı kategorisi: Delegate, Find, Generic, Predicate | » yorum bırak;