We've got a generic class which contains a private class which uses the outer class's generic type parameter. Example:
public class Foo<T>
{
private class Bar : IGrouping<Guid,T>{
}
}
The problem is that we get a compile error in a unit test project which states
"The Type or method has 2 generic parameter(s), but 1 generic argument(s) were provided. A generic argument must be provided for each generic parameter."I cranked up MSBuild verbosity (Tools > Options > Projects and Solutions > Build and Run). Looking at the error location, it points to the Microsoft.TeamTest.targets file. I was able to narrow it down to this class structure above. If I replace the private class Bar with concrete generic parameters in the class definition (see below), the unit test compiles fine:
private class Bar : IGrouping<Guid,int>{
}
I need to provide that second generic parameter generic to accept whatever the type is in the outter class. Thoughts on this one?
To clarify, the compile error is in the Unit Test Project, not the code listed above (which compiles fine). Perhaps the private accessor generation is choking in the MS unit test infrastructure?
Here's [almost] the entire actual code:
public class CategoryStorageService<T> : StorageServiceBase<T>, ICategoryStorageService<T> where T : IStorageContent, new()
{
/// <summary>
/// Returns a nested object graph of category-items
/// </summary>
/// <param name="categories"></param>
/// <returns></returns>
public IEnumerable<IGrouping<StorageCategory, T>> GetContent(params StorageCategory[] categories)
{
var results = this.GetContent(categories.Select(c => c.ID).ToArray());
foreach (var result in results)
{
yield return new LocalNameGrouping(
categories.First(c => c.ID == result.Key.ID),
result);
}
}
/// <summary>
/// Returns a nested object graph of categories, each containing their items
/// </summary>
/// <param name="categories">The ID(s) of the category(ies) to fetch</param>
/// <returns></returns>
private IEnumerable<IGrouping<StorageCategory, T>> GetContent(params Guid[] categories)
{
// implementation removed
return null;
}
private class LocalNameGrouping : IGrouping<StorageCategory, T>
{
private IEnumerable<T> items;
private StorageCategory category;
public LocalNameGrouping(StorageCategory localCategory, IGrouping<StorageCategory, T> items)
{
this.items = items;
string name = string.IsNullOrEmpty(localCategory.DisplayName) ? items.Key.DisplayName : localCategory.DisplayName;
this.category = new StorageCategory { DisplayName = name, ID = items.Key.ID };
}
#region IGrouping<StorageCategory,T> Members
public StorageCategory Key
{
get { return category; }
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return items.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
}