blah blah blah is here! blah blah » Close

up0down
link

Can I somehow implement a method in a list item?

For example, if this is the class I base my list off of:

class TestListItem
{

public string Name;
public string Address;

public TestListItem(string name,string address)
{
Name = name;
Address = address
}

public int TestMethod(int i)
{
return i;
}

}


Then I'd like to be able to do the following:

public List<T> junk = new List<T>();

junk.AddNew(new TestListItem("blah","blah"));

junk[0].TestMethod(5); //Not allowed

last answered 2 years ago

3 answers

link

What you first need to do is to define an interface which has one member, ToByteArray().

GroupListItem and all the other classes that will be used with DeviceDataTable<T> will then need to implement this interface (no problem as they all have ToByteArray() methods anyway).

Finally, you need to impose a constraint on DeviceDataTable<T> whereby T implements the interface so that the compiler will know that it's OK to call ToByteArray() on an instance of T referenced within the generic class:

interface IListItem // for want of a better name
{
byte[] ToByteArray(byte[] flrow);
}

class GroupListItem : IListItem // implements interface
{

public const int FIELD_SIZE_NAME = 32;
public const int MAX_USERS_IN_GROUP = 16;
public byte UID;
public string Name;
public List<UserListItem> Users;

public GroupListItem(string name)
{
Name = name;
Users = new List<UserListItem>();
}

public byte[] ToByteArray(byte[] flrow)
{
Int32 i=0;

flrow[i] = UID;
System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
encoding.GetBytes(this.Name.Substring(0,FIELD_SIZE_NAME-1)).CopyTo(flrow, i += FIELD_SIZE_NAME);

return flrow;
}

}


// apply constraint to T
class DeviceDataTable<T> : IEnumerable<T> where T: IListItem
{
private List<T> table = new List<T>();

public T this[int pos]
{
get
{
return table[pos];
}
set
{
table[pos] = value;
}
}

public void AddRow(T r)
{
table.Add(r);

//Add ID management and call to r.ToByteArray()
}

public void RemoveRow(Int32 i)
{
table.RemoveAt(i);

//Add ID management and call to r.ToByteArray()

}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return table.GetEnumerator();
}


IEnumerator IEnumerable.GetEnumerator()
{
return table.GetEnumerator();
}

}

eeboy
499

Thanks! That appears to be exactly what I am after... but (of course) I have found out that interfaces can't contain a field. I tried to add the field 'byte UID;' to the interface and that results in an error.

eeboy
499

I've learned that I can't expose a field from an interface. Instead I must encapsulate the data as a property. Works well now.

up0down
link

You need to specify TestListItem as the type argument of the generic List. The following program works fine:

using System;
using System.Collections.Generic;

class TestListItem
{

public string Name;
public string Address;

public TestListItem(string name,string address)
{
Name = name;
Address = address;
}

public int TestMethod(int i)
{
return i;
}
}

class Test
{
public static List<TestListItem> junk = new List<TestListItem>();

static void Main()
{
junk.Add(new TestListItem("blah","blah"));
int i = junk[0].TestMethod(5);
Console.WriteLine(i);
Console.ReadKey();
}
}

eeboy
499

I can't format code in a comment so I'll post an answer...

up0down
link

Sorry... I cut some things out to simplify the post and I realize now that I shouldn't have. Here is what I have:

class GroupListItem
{

public const int FIELD_SIZE_NAME = 32;
public const int MAX_USERS_IN_GROUP = 16;
public byte UID;
public string Name;
public List<UserListItem> Users;

public GroupListItem(string name)
{
Name = name;
Users = new List<UserListItem>();
}

public byte[] ToByteArray(byte[] flrow)
{
Int32 i=0;

flrow[i] = UID;
System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
encoding.GetBytes(this.Name.Substring(0,FIELD_SIZE_NAME-1)).CopyTo(flrow, i += FIELD_SIZE_NAME);

return flrow;
}

}



class DeviceDataTable<T> : IEnumerable<T>
{
private List<T> table = new List<T>();

public T this[int pos]
{
get
{
return table[pos];
}
set
{
table[pos] = value;
}
}

public void AddRow(T r)
{
table.Add(r);

//Add ID management and call to ToByteArray()
}

public void RemoveRow(Int32 i)
{
table.RemoveAt(i);

//Add ID management and call to ToByteArray()

}

IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return table.GetEnumerator();
}


IEnumerator IEnumerable.GetEnumerator()
{
return table.GetEnumerator();
}

}


Above is the exact example. Notice that I have made DeviceDataTable<T> so that I could add methods to the generic list to make it suitable for my use. GroupListItem is just one class which will be used with my DeviceDataTable. However, all classes that will be used with DeviceDataTable<T> will support a method called ToByteArray(). Given that the DeviceDataTable<T> can be based on GroupListItem or any other class that I make... how can I implement a call to the GroupListItem ToByteArray method from within a particular instance of DeviceDataTable<>.

Feedback