Tuesday, March 1, 2011

Improve Perfomance in ASP.net

While developing any web site, one should keep some points in mind.
1) Set debug=false under compilation as follows:



2) Use Server.Transfer instead of Response.Redirect.

3) Always check Page.IsValid when using Validator Controls

4) Use Foreach loop instead of For loop for String Iteration.

5) Use Client-Side Validation. (but not all the time you have to validate even on the server side)

6) Check “Page.IsPostBack”. To avoid repetition code execution.

7) GIF and PNG are similar, but PNG typically produces a lower file size. (True, but some browsers not supporting PNG format)

8) Use the AppOffline.htm when updating binaries

9) Turn off Tracing unless until required. (by default it's off, use on the pages where it's required)



10) Precompiled pages and disable AutoEventWireup; setting the AutoEventWireup attribute to false in the Machine.config file.
11) Turn off Session State, if not required.



12) Select the Release mode before making the final Build for your application.

This option is available in the Top Frame just under the Window Menu option. By default, the Mode is Debug

13) Disable ViewState when not required.

EnableViewState="false"

14) Avoid frequent round trips to the Database.

15) Use Caching to improve the performance of your application.

16) Validate all Input received from the Users.

17) Use Finally Method to kill resources. (But not in the case of using)

18) The String and Stringbuilder Magic.

It is nice to use Stringbuilder instead of String when string are Amended. Strings occupy different memory location in every time of amended where stringbuilder use single memory location

19) Never use object value directly; first get object value in local variable and then use. It takes more time then variable reading.

20) Avoid Exceptions: Use If condition (if it is check proper condition)

21) Code optimization: Avoid using code like x = x +1; it is always better to use x+=1.

22) Data Access Techniques: DataReaders provide a fast and efficient method of data retrieval. DataReader is much faster than DataSets as far as performance is concerned

23) Before doing a bulky ASP code processing, you can check to make sure Response.IsClientConnected.

24) As always, avoid session variables because each ASP page runs in a different thread and session calls will be serialized one by one. So, this will slow down the application. Instead of session variables you can use the QueryString collection or hidden variables in the form which holds the values.

25) Enabling buffering will improve the performance, like

<% response.buffer=true %>

Then use:

<% response.flush=true %> 26) Use Repeater control instead of DataGrid , DataList, Because It is efficient, customizable, and programmable.

27) Data listing is more time consume when large data are retrieve from database.

Paging will display only particular data but take load of all data.

Fetch only data that is needed for current page.

28) Avoid Inline JavaScript and CSS

29) Use single css file instead of multiple css file.

Try your best to combine all your CSS based classes into a single .css file as lot of .css files will cause a large amount of requests, regardless of the file sizes.

.css files are normally cached by browsers, so a single and heavy .css file doesn’t cause a long wait on each page request.

Inline .css classes could make HTML heavy, so again: go ahead with a single.css file.

30) Reduce cookie size

31) Compress CSS, JavaScript and Images

Online compressors are available; to compress file please refers following web and Replace your file content with optimize code.

http://iceyboard.no-ip.org/projects/css_compressor for CSS compression

www.xtreeme.com/javascript-optimizer/ . For JS Compression

32 .Use Cache appropriately

i. Page output caching:

<%@ OutputCache Duration="3600" VaryByParam="none" %>

ii. Page fragment caching:

Write a Page output caching code into each User Control

iii. Data caching:



33) Use server side compression software such as Port80s http://www.port80software.com/products/httpzip/

34) Usage of "using" and I don't know why it's not yet published.

35) Don't make the member variables public or proteted, try to keep private and use public/protected as properties.

36) Use strString=string.Empty instead of strString="" . [And perhaps instead of strString=null also (?)]

37) Make your page files as light as possible. That is try to avoid unnecessary markups, e.g. use div elements instead of tables.

38) Write static messages in div and make it visible when necessary. This is faster than letting server set Text property of your label or div.

39) Retrieve data from database at once, if possible. Don't add up to database trip as far as possible. For this, combine the datafields from different tables and select them.

40) Use short ID name for WebControl.

The Basics of CSS3

The Basics of CSS3

These CSS3 properties are commonly used to enhance layout and good to know.
RGBA
The first three values are RGB color values and the last value is the level of the transparency (0 = transparent and 1 = opaque).



RBGA can be applied to any properties associated with color such as font color, border color, background color, shadow color, etc.



Text Shadow
Text shadow is structured in the following order: x-offset, y-offset, blur, and color;



Set a negative value for x-offset to shift the shadow to the left. Set a negative value for y-offset to shift the shadow to the top. Don’t forget you can use RGBA values for the shadow color.



You can also specify a list of text-shadow (separated by a comma). The following example uses two text-shadow declarations to make a letter press effect (1px top and 1px bottom).

text-shadow: 0 1px 0 #fff, 0 -1px 0 #000;



Border Radius
The shorthand for border radius is similar to the padding and margin property (eg. border-radius: 20px). In order for the browsers to render the border radius, add "-webkit-" in font of the property name for webkit browsers and "-moz-" for Firefox.



You can specify each corner with a different value. Note Firefox and Webkit has different property names for the corners.



Box Shadow
The structure for box shadow is same as the text-shadow property: x-offset, y-offset, blur, and color.



Again, you can apply more than one box shadow. The following example is a list of three box shadow declarations.

-moz-box-shadow:
-2px -2px 0 #fff,
2px 2px 0 #bb9595,
2px 4px 15px rgba(0, 0, 0, .3);

New Ranking Functions within SQL Server 2005

New Ranking Functions within SQL Server 2005

With SQL Server 2005, Microsoft introduced a number of new features. These new features make it easier for a DBA or SQL Server developer to code against and to maintain SQL Server databases. In this article I will discuss the new ranking functions provided with SQL Server 2005. These new functions make it much easier for you to code your T-SQL to associate a ranking to your result set. As I discuss each of the new ranking functions I will provide one or more examples to help illustrate how these new functions work.

What are Ranking Functions
Ranking functions are functions that allow you to sequentially number your result set. These functions can be used to provide you with a number of different sequential numbering schemes. For example you can number each row in your result set sequentially where the first row has a ranking number of 1, the second row has a ranking of 2, third row has 3, and so on. You can also use these ranking functions to sequentual number groups, so each group would have a numbering scheme of 1,2, 3, and then the next group would start over with 1, 2, 3, etc..

Test Data for My Examples
In order to provide examples of each ranking function I need to have some test data that the ranking function will process against. For my test data I will use a simple “Person” table. This table will consist of three columns “FirstName”, “Age” and “Gender”. Below is the code to create and populate my sample test data file.

SET NOCOUNT ON
CREATE TABLE Person(
FirstName VARCHAR(10),
Age INT,
Gender CHAR(1))
INSERT INTO Person VALUES ('Ted',23,'M')
INSERT INTO Person VALUES ('John',40,'M')
INSERT INTO Person VALUES ('George',6,'M')
INSERT INTO Person VALUES ('Mary',11,'F')
INSERT INTO Person VALUES ('Sam',17,'M')
INSERT INTO Person VALUES ('Doris',6,'F')
INSERT INTO Person VALUES ('Frank',38,'M')
INSERT INTO Person VALUES ('Larry',5,'M')
INSERT INTO Person VALUES ('Sue',29,'F')
INSERT INTO Person VALUES ('Sherry',11,'F')
INSERT INTO Person VALUES ('Marty',23,'F')
ROW_NUMBER Function
The first ranking function I will discuss is the ROW_NUMBER function. This function returns a sequential number starting at 1 for each row or grouping within your result set. The ROW_NUMBER function has the following calling syntax:

ROW_NUMBER ( ) OVER ( [ ] )Where the:

” is a column or set of columns used to determine the grouping in which the ROW_NUMBER function applies sequential numbering.

” is a column or set of columns used to order the result set within the grouping (partition).

To demonstrate how to use the ROW_NUMBER function, my first example below will sequentially number all the rows in my Person table, and order them by Age.

SELECT ROW_NUMBER() OVER (ORDER BY Age) AS [Row Number by Age],
FirstName,
Age
FROM Person
Here is the result set for the above T-SQL code:

Row Number by Age FirstName Age
-------------------- ---------- -----------
1 Larry 5
2 Doris 6
3 George 6
4 Mary 11
5 Sherry 11
6 Sam 17
7 Ted 23
8 Marty 23
9 Sue 29
10 Frank 38
11 John 40
Here you can see I have sequentially numbered all my Person table rows starting from 1, and the result set is ordered by the Age column. This ordering was accomplished by placing the “ORDER BY Age” criteria in the ORDER BY clause of the ROW_NUMBER function.

Suppose you do not want your result set to be ordered, but you want to simply just sequentially number each row. The ROW_NUMBER function requires an ORDER BY clause, so something is needed in this clause. In the following query I specified “SELECT 1” for the ORDER BY clauses, doing this just returned my rows physically how they where stored, and sequentially numbered them starting from 1:

SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS [Row Number by Record Set],
FirstName,
Age
FROM Person
Here is the result set from running the above query:

Row Number by Record Set FirstName Age
------------------------ ---------- -----------
1 Ted 23
2 John 40
3 George 6
4 Mary 11
5 Sam 17
6 Doris 6
7 Frank 38
8 Larry 5
9 Sue 29
10 Sherry 11
11 Marty 23
The ROW_NUMBER function not only allows you to order the entire row set, but you can also use the PARTITION clause to sequentially number groups of rows. Rows will be sequentially numbered within each unique partition value. The sequential number will restart at 1 for each new partition value in your record set. Take a look at the following query:

SELECT ROW_NUMBER() OVER (PARTITION BY Gender ORDER BY Age) AS [Partition by Gender],
FirstName,
Age,
Gender
FROM Person
When I run this query, this is my result set:

Partition by Gender FirstName Age Gender
-------------------- ---------- ----------- ------
1 Doris 6 F
2 Mary 11 F
3 Sherry 11 F
4 Sue 29 F
1 Larry 5 M
2 George 6 M
3 Sam 17 M
4 Ted 23 M
5 Marty 23 M
6 Frank 38 M
7 John 40 M
In this example I partitioned by Gender, and ordered by Age. Doing this allowed me to sequentially number the female records in my Person table by age, and then have the sequential numbering start over again for the male group.

RANK Function
Sometimes you want a row that has the same order by column value as another row to have the same ranking. If this is the case then the RANK() function will help you. The RANK function has the following calling syntax:

RANK ( ) OVER ( [ ] )Where the:

” is a column or set of columns used to determine the grouping in which the RANK function applies sequential numbering.

” is a column or set of columns used to order the result set within the grouping (partition).

The RANK function sequentially numbers a record set, but when two rows have the same order by value then they get the same ranking. The ranking value still gets incremented when two rows have the same order by value, so that when a new ranking order by value is encountered the ranking value on that new row will be 1 more than the number of proceeding rows. Let me show you a couple of examples to help you better understand the RANK function.

In this first example I want to rank my record set by Age:

SELECT RANK() OVER (ORDER BY Age) AS [Rank by Age],
FirstName,
Age
FROM Person
Here is the output for this command:

Rank by Age FirstName Age
-------------------- ---------- -----------
1 Larry 5
2 Doris 6
2 George 6
4 Mary 11
4 Sherry 11
6 Sam 17
7 Ted 23
7 Marty 23
9 Sue 29
10 Frank 38
11 John 40
By looking at this output you can see that whenever rows have the same Age value their “Rank by Age” value are the same. You can see this for “Doris” and “George”, “Mary” and “Sherry”, as well as “Ted” and “Marty”. Each of these row pairs have the same “Rank by Age” value. Note that “Doris” and “George” both have a ranking of 2, but the ranking for “Mary” the next unique Age doesn’t have a ranking value of 3, but instead has a ranking of 4. This is because “Mary” is the forth record returned in the record set, and the RANK() functions takes this into account when setting the ranking value of the next unique “Rank by Age” value.

If you want to have multiple rankings in your record set, where each ranking is for a specific group you need to use the “PARTITION BY” clause of the RANK function. Below is an example where I grouped my ranking by Gender, and ordered each ranking by Age:

SELECT RANK() OVER (PARTITION BY Gender ORDER BY Age) AS [Partition by Gender],
FirstName,
Age,
Gender
FROM Person
Here is the results of running the above query:

Partition by Gender FirstName Age Gender
-------------------- ---------- ----------- ------
1 Doris 6 F
2 Mary 11 F
2 Sherry 11 F
4 Sue 29 F
1 Larry 5 M
2 George 6 M
3 Sam 17 M
4 Ted 23 M
4 Marty 23 M
6 Frank 38 M
7 John 40 M
Here you can see that the “F” Gender started ranking at 1 and goes through 4, then the ranking starts over with 1 when the first “M” Gender is encountered.

DENSE_RANK Function
The DENSE_RANK function is similar to the RANK function, although this function doesn’t produce gaps in the ranking numbers. Instead this function sequentially ranks each unique ORDER BY value. With the DENSE_RANK function each row either has the same ranking as the preceeding row, or has a ranking 1 greater then the prior row. The DENSE_RANK function has the same syntax as the RANK function.

Here I use the DENSE_RANK function to rank all my Person records by Age:

SELECT DENSE_RANK() OVER (ORDER BY Age) AS [Dense Rank by Age],
FirstName,
Age
FROM Person
This code produces the following output:

Dense Rank by Age FirstName Age
-------------------- ---------- -----------
1 Larry 5
2 Doris 6
2 George 6
3 Mary 11
3 Sherry 11
4 Sam 17
5 Ted 23
5 Marty 23
6 Sue 29
7 Frank 38
8 John 40
Here you can see the “Dense Rank By Age” column numbers are sequential without any gaps. And when two rows have the same ORDER BY value they have the same ranking like “Ted” and “Marty”.

NTILE Function
The last ranking function is the NTILE function. This function is used to break up a record set into a specific number of groups. The NTILE function also uses similar syntax as the other ranking functions.

In this first example, I want to group my Person records into three different groups of records. I want these groups to be based on the Age column. To do that I would run the following T-SQL:

SELECT FirstName,
Age,
NTILE(3) OVER (ORDER BY Age) AS [Age Groups]
FROM Person
Here is my result set from the above T-SQL command:

FirstName Age Age Groups
---------- ----------- --------------------
Larry 5 1
Doris 6 1
George 6 1
Mary 11 1
Sherry 11 2
Sam 17 2
Ted 23 2
Marty 23 2
Sue 29 3
Frank 38 3
John 40 3
In my result set I ended up with three different “Age Groups”. The first age group goes from Age 5 to Age 11, the second age group goes from 11 to 23, and the last age group is 29 to 40. The NTILE function just evenly divides your record set into the number of groups the NTILE function requests. By using the NTILE function each record in a group is give the same ranking.

The NTILE function is very useful if you only want to return a specific grouping of records. Below is an example where I returned only the middle group (Age Group = 2) from my prior example:

SELECT FirstName,
Age,
Age AS [Age Group]
FROM ( SELECT FirstName,
Age,
NTILE(3) OVER (ORDER BY Age) AS AgeGroup
FROM Person) A
WHERE AgeGroup = 2
Here you can see I only returned the second Age Group:

FirstName Age Age Group
---------- ----------- -----------
Sherry 11 11
Sam 17 17
Ted 23 23
Marty 23 23
Conclusion
Coding a process to sequential number your record sets used to take a number of lines of code. SQL Server 2005 solved this coding dilemma by providing some new ranking functions. Hopefully the next time you need to sequential number a record set, one of the new ranking functions in SQL Server 2005 will make your number task, a trivial task.

PIVOT & UNPIVOT Operators in SQL Server 2008

PIVOT & UNPIVOT Operators in SQL Server 2008

PIVOT is a new T-SQL operator introduced in SQL Server 2008 which can be used to rotate rows into columns and can create a crosstab query. You can specify the PIVOT operator in FROM clause of your query.

Using PIVOT

Specify the desired values that you want to see in SELECT statement and FROM clause contains the PIVOT statement. Let us take an example




The following query uses ADVENTUREWORKS database which uses the order years as columns.

SELECT
CustomerID,
[2001] AS Y2001, [2002] AS Y2002, [2003] AS Y2003, [2004] AS Y2004
FROM
(
SELECT CustomerID, DATEPART(yyyy, OrderDate) AS OrderYear, TotalDue
FROM Sales.SalesOrderHeader
) AS piv
PIVOT
(
SUM(TotalDue) FOR OrderYear IN([2001], [2002], [2003], [2004])
) AS child
ORDER BY CustomerIDThe FROM clause create the values that you want to see in rows of the newly created columns. We used the FOR operator to list the values that we want to pivot in the OrderYear Column.


USING UNPIVOT

UNPIVOT operator can be used to normalize the data that is already pivoted. Let us take the example. Create a Vendor Employee table and insert some values in it.

CREATE TABLE VEmployee
(VendorID int,
Emp1Orders int,
Emp2Orders int,
Emp3Orders int,
Emp4Orders int,
Emp5Orders int)
GOINSERT INTO VEmployee VALUES(1, 4, 3, 5, 4, 4)

INSERT INTO VEmployee VALUES(2, 4, 1, 5, 5, 5)

INSERT INTO VEmployee VALUES(3, 4, 3, 5, 4, 4)

INSERT INTO VEmployee VALUES(4, 4, 2, 5, 4, 4)

INSERT INTO VEmployee VALUES(5, 5, 1, 5, 5, 5)



SELECT VendorID, Employee, Orders AS NumberOfOrders
FROM
(SELECT VendorID, Emp1Orders, Emp2Orders, Emp3Orders, Emp4Orders, Emp5Orders
FROM VEmployee
) AS p
UNPIVOT
(
Orders FOR Employee IN
(Emp1Orders, Emp2Orders, Emp3Orders, Emp4Orders, Emp5Orders)
) AS unpvt

ASP.NET Collections: The IList Interface

IList Fundamentals


Introduction


While it provides the minimum functionality of a collection, the System.Collections.ICollection (and the System.Collections.Generic.ICollection) interface is not equipped to perform the regular operations of a collection class, such as adding, retrieving, or deleting items from a set.

To assist you with creating a collection class as complete as possible, the .NET Framework provides an interface named IList. The IList interface is defined in the System.Collections namespace and its equivalent of the same name is defined in the System.Collections.Generic namespace. The interface is equipped with the methods necessary to add, insert, delete, or retrieve items from a collection. Because the functionalities of these methods may not suit you, to use these features, you must create a class that implements them.

Implementing IList



As mentioned above, to create a collection, you can derive it from the IList interface. Here is an example:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
public BookList()
{

}
}
This System.Collections.IList interface is declared as follows:

public interface IList : ICollection, IEnumerable
This System.Collections.Generic.IList interface is declared as follows:

public interface IList : ICollection,
IEnumerable,
IEnumerable

This means that the IList interface exdends both the ICollection and the IEnumerable interfaces. This also implies that you must implement the members of these parent interfaces. In other words, you must implement the Count property, the SyncRoot property, the IsSynchronized property, and the CopyTo() method of the ICollection interface. From what we learned with ICollection, here are examples of implementing these members for the System.Collections.IList interface:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
private int counter;
private object[] objs;

public BookList()
{
counter = 0;
objs = new array[5];
}

public virtual int Count
{
get { return items; }
}

public virtual bool IsSynchronized
{
get { return false; }
}

public virtual object SyncRoot
{
get { return this; }
}

public virtual void CopyTo(Array ary, int index)
{
}
}
You must also implement the System.Collections.GetEnumerator() (or the System.Collections.Generic.GetEnumerator()) method of the System.Collections.IEnumerable (or of the System.Collections.Generic.IEnumerable) interface. If you do not have time to completely implement it, you can simply return null. Here is an example for the System.Collections.IList interface:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public IEnumerator GetEnumerator()
{
return null;
}
}
The Size of a Collection


A Fixed-Size Collection



In the next sections, we will see how to add values to a list of a database. As you add or insert values in a list, the Count property grows. If your collection is array-based, when you start it, you specify the number of values that the list will contain. In theory, you cannot add new values beyond that number. In reality, you can increase the size of an array and then add a new item. If your collection is a linked list, you are also not confined to the laws of space (unless your computer runs out of memory).

If you create a list whose number of values must be constant, the user cannot add values beyond the maximum allowed number. Therefore, before adding a value, you can first check whether the collection has a fixed size or not. To give you this information, the IList interface is equipped with a Boolean read-only property named IsFxedSize. This property simply lets the user know whether the collection has a fixed number of items.

Here is an example of implementing this property for the System.Collections.IList interface:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public virtual bool IsFixedSize
{
get { return false; }
}
}
A Read-Only Collection



Most databases are meant to receive new values. If you want, you can create a list that cannot receive new values. To support this, the IList interface is equipped with the Boolean IsReadOnly property. If a list is read-only, it would prevent the clients from adding items to it.

Here is an example of implementing the IsReadOnly property for the System.Collections.IList interface:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public virtual bool IsReadOnly
{
get { return false; }
}
}
Populating the Collection


Adding an Item



As it should be obvious, the primary operation to perform on a list is to populate it with at least one value. To support this, the System.Collections.IList interface is equipped with a method named Add. Its syntax is:

int Add(object value);
This method takes one argument as the value to add to the list. If your collection is an array, you can first check that there is still enough room in the list to add a new item. In reality, this is never an issue with the System.Collections.IList interface:

If there is still room in the collection, the value would be added to the list
If there is not enough room, the value would simply not be added. There would not be a problem and the program would not crash. In fact, no exception would be thrown if the value was not added because of lack of space. On the other hand, since the compiler would not let you know that there was a problem with "logistic", you may not know whether the value was added or not. Therefore, if you are concerned with knowing whether the value was added, you must provide this functionality yourself
If the method succeeds with the addition, it returns the position where the value was added in the list. This is usually the last position in the list.

Here is an example:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public virtual int Add(object value)
{
// Check whether there is still room in
// the array to add a new item
if (counter < objects.Length)
{
// Since there is room, put the new item to the end
objects[items] = value;
// increase the number of items
objects++;
// Return the index of the item that was added
return counter - 1;
} // Since the item could not be added, return a negative index
else
return -1;
}
}
Inserting an Item



When you call the System.Collections.IList.Add() method, it adds the new value to the end of the list. Sometimes, you will want the new value to be insert somewhere inside the list. To support this operation, both the System.Collections.IList and the System.Collections.Generic.IList interfaces provide a method named Insert. The syntax of the System.Collections.IList.Insert() method is:

void Insert(int index, object value);
The syntax of the System.Collections.Generic.IList.Insert() method is:

void Insert(int index, T value);
This method takes two arguments. The second argument is the value that will be inserted into the list. The argument must hold a valid value. Because this method takes an Object object, if your collection is using a different type of value, you may have to cast it to Object. The first argument is the index of the item that will precede the new one.

As mentioned for the System.Collections.IList. Add() method, there are a few things you should know about this operation's success or lack of it:

If the index argument holds a negative value or a value higher than the allowed number (for example if the list is an array) of the items (depending on how you implement the method), the new value would not be added, the compiler would not throw an exception, and therefore nothing would let you know that the value was not added. If you want to find out whether the value was formally or actually inserted or not, you must create the functionality yourself
If the value argument is not valid, again depending on how you structure your class, either the value would not be inserted or something else would go wrong. Fortunately, if the value argument is of the type of a class you created yourself, the compiler would produce an error such as letting you know that the argument is holding a value that is not conform to its property or member variable
Locating an Item in the Collection


This Default Item of the Collection



While using a list, various operations require that you know the object you are currently accessing. To provide this operation, you must create an indexed property. This property should take an index and return the type of object that makes up the list. Here is an example:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public virtual object this[int index]
{
get { return objects[index]; }

set
{
objects[index] = value;
}
}
}
After creating this property, you can then access an item using its index and applying the [] operator on its instance. Remember that if you want to use foreach, you must appropriately implement the IEnumerable.GetEnumerator() method.

Enumerating the Collection foreach Item



One of the most valuables features of the C# is the ability to use the foreach loop to enumerate the members of a collection. To make this possible, you must implement the IEnumerator interface in your collection class. Following the rules of interface implementation, you must override the members of IEnumerator.

Checking the Existence of an Item



One of the routine operations you can perform on a list is to find out whether it contains a certain value. To assist you with this operation, the System.Collections.IList interface is equipped with a method named Contains. Its syntax is:

bool Contains(object value);
This method takes as argument the value to look for. If the value is found in the list, the method returns true. If no value is found in the collection, this method returns false.

Here is an example of implementing this method:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public bool Contains(object value)
{
for (int i = 0; i < Count; i++)
if (objects[i] == value)
return true;
return false;
}
}
This method calls the Equals() method of the objects that make up the list to find out whether the value argument exists in the collection. If this method produces a wrong result, especially if you are using your own class to represent the item, you may have to override your own Equals() method.

Getting the Index of an Item



The System.Collections.IList.Contains() method is used to check whether a particular value (already) exists in the collection. If you know that a certain item exists in the collection but you don't know its index inside the list, the IList interface can assist you through a method named IndexOf. Its syntax is:

int IndexOf(object value);
This method takes as argument the value to look for in the list. If the value is found in the collection, the method returns its index. If there is no value defined like that, the method returns -1. Here is an example of implementing this method:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public int IndexOf(object value)
{
for (int i = 0; i < Count; i++)
if (objects[i] == value)
return i;
return -1;
}
}
This method calls the Equals() method of the objects that make up the collection to find out whether the value argument exists in the list. If this method produces a wrong result, especially if you are using your own class to represent the value, you may have to override your own Equals() method.

Deleting Values in the List


Deleting a Value by its Index



If a value is not necessary in your list, you can delete it. Probably the simplest way to delete a value is to specify its position in the list. To support this operation, both the System.Collections.IList and the System.Collections.Generic.IList interfaces are equipped with a method named RemoveAt. The syntax of the RemoveAt() method is is the same for both interfaces and it is:

void RemoveAt(int index);
This method takes as argument the index of the value to be removed. Here is an example:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public void RemoveAt(int index)
{
if ((index >= 0) && (index < Count))
{
for (int i = index; i < Count - 1; i++)
objects[i] = objects[i + 1];
items--;
}
}
}
Deleting an Item by its Value



The problem with deleting a value based on its index is that, if you are not sure, you could delete the wrong value. An alternative is to first precisely define the value you want to get rid of, and then hand the value itself to the compiler that would remove it. To support this approach, the System.Collections.IList interface is equipped with a method named Remove() and whose syntax is:

void Remove(object value);
This method takes as argument the value to be deleted. This means that the compiler will first look for the value in the list. If it finds that value, it removes it. If there is no value like that, nothing happens (the compiler doesn't throw an exception. Here is an example of implementing this method:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
. . . No Change

public virtual void Remove(Object value)
{
RemoveAt(IndexOf(value));
}
}
Clearing a Collection



To remove all value from a list at once, you can implement Clear() method of the System.Collections.IList interface. Its syntax is:

void Clear();
Here is an example of implementing it:

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;

///
/// Summary description for BookList
///

public class BookList : IList
{
private int counter;
private object[] objects;

public BookList()
{
counter = 0;
objects = new object[5];
}

public virtual int Count
{
get { return counter; }
}

public virtual bool IsSynchronized
{
get { return false; }
}

public virtual object SyncRoot
{
get { return this; }
}

public virtual void CopyTo(Array ary, int index)
{
}

public IEnumerator GetEnumerator()
{
return null;
}

public virtual bool IsFixedSize
{
get { return false; }
}

public virtual bool IsReadOnly
{
get { return false; }
}

public virtual int Add(object value)
{
// Check whether there is still room in
// the array to add a new item
if (counter < objects.Length)
{
// Since there is room, put the new item to the end
objects[counter] = value;
// increase the number of items
counter++;
// Return the index of the item that was added
return counter - 1;
} // Since the item could not be added, return a negative index
else
return -1;
}

public virtual void Insert(int index, object value)
{
}

public virtual object this[int index]
{
get { return objects[index]; }

set
{
objects[index] = value;
}
}

public virtual bool Contains(object value)
{
for (int i = 0; i < Count; i++)
if (objects[i] == value)
return true;
return false;
}

public virtual int IndexOf(object value)
{
for (int i = 0; i < Count; i++)
if (objects[i] == value)
return i;
return -1;
}

public virtual void RemoveAt(int index)
{
if ((index >= 0) && (index < Count))
{
for (int i = index; i < Count - 1; i++)
objects[i] = objects[i + 1];
counter--;
}
}

public virtual void Remove(Object value)
{
RemoveAt(IndexOf(value));
}

public virtual void Clear()
{
counter = 0;
}
}