Introduction to generics in C# Part 4


In the previous post we saw how to build generic functions. It’s not necessary to make an entire class generic if we want to keep the functions independent of any class level type parameters. We saw an example, a configuration settings reader, where it was unnecessary to declare the return type on the class level. That would put a constraint on the usage of a single configuration reader instance. Instead, we let the caller define the return type on the ReadConfigurationValue function which makes the configuration reader class more flexible.

In this post we’ll look at declaring multiple generic parameters.

Multiple generic parameters

So far in this mini-series we’ve only seen examples where a single type parameter was declared, e.g.:

public class ConfigurationReaderService<T>

However, there’s nothing stopping us from providing as many generic type parameters as we need. Let’s revisit the rudimentary domain-based example of the first post in this series. We know that every domain object has an ID and we want to be able to search for any domain object by ID in the data repository, e.g. an MS SQL database. Also recall that the ID type can vary, it can be an integer, a GUID, a random string or whatever.

Let’s take the Customer and Order classes:

public abstract class Domain<T>
	public T Id { get; }

	public Domain(T id)
		Id = id;
public class Customer : Domain<int>
	public Customer(int id, string name) : base(id)
		Name = name;

	public string Name { get; }

public class Order : Domain<Guid>
	public Order(Guid id, string address) : base(id)
		Address = address;

	public string Address { get; }

We can have a generic interface that will let us build multiple implementations for various objects. We’ll keep the repository interface simple and let the caller only search for an object by its ID:

public interface IRepository<DomainType, IdType>
	DomainType FindBy(IdType id);

Let’s see what we have here:

  • We have 2 type parameters: DomainType, IdType
  • They might as well be called ‘T’ and ‘U’ or ‘K’ and ‘V’ but I think that with multiple type parameters a more descriptive type name can be useful for the caller
  • We are free to refer to these types later on in the interface function FindBy

Here’s an implementation stub for the Customer and the Order repository:

public class CustomerRepository : IRepository<Customer, int>
	public Customer FindBy(int id)
		return new Customer(id, "Found you!!!");

public class OrderRepository : IRepository<Order, Guid>
	public Order FindBy(Guid id)
		return new Order(id, "Found you by your GUID!!!");

We can add a whole range of type parameters to our classes and functions. An example from .NET is the generic Func delegate object. It has no fewer than 17 overloads ranging from a single output parameter:

public delegate TResult Func<out TResult>(
	T arg

…to 16 input parameters and 1 output parameter:

public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(
	T1 arg1,
	T2 arg2,
	T3 arg3,
	T4 arg4,
	T5 arg5,
	T6 arg6,
	T7 arg7,
	T8 arg8,
	T9 arg9,
	T10 arg10,
	T11 arg11,
	T12 arg12,
	T13 arg13,
	T14 arg14,
	T15 arg15,
	T16 arg16

So far we’ve only seen examples where we could declare just any type of parameter type, like here:

public interface IConfigurationRepository
	T ReadConfigurationValue<T>(string key, T defaultValue, bool throwException = false);

We can potentially pass in just any object type for ‘T’: a string, a Customer, a GUID, etc. However, there are occasions where want to be able to constrain the types that the generic method or class can handle. We’ll see how that works in the next post.

View all various C# language feature related posts here.


About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog


Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: