Reputation: 882
I must be missing something obvious but the following fails with a compile error:
internal static IEnumerable<T> GetEntitiesWithCommaSeparatedRowKeys<T>(
string tableName, string partitionKey,
string commaDelimitedStringOfRowKeys) where T: TableEntity
{
....
TableQuery<T> entitiesQuery = new TableQuery<T>().Where(
TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey",
QueryComparisons.Equal, partitionKey),
TableOperators.And,
AzureHelper.GetFilterConditionForCommaDelimitedStringOfRowKeys(commaDelimitedStringOfRowKeys)
));
// compile error on this line
IEnumerable<T> entities = table.ExecuteQuery<T>(entitiesQuery);
...
}
The error I get is:
'T' must be a non-abstract type with a public parameterless constructor
in order to use it as parameter 'TElement' in the generic type or
method 'Microsoft.WindowsAzure.Storage.Table.CloudTable.ExecuteQuery<TElement>
(Microsoft.WindowsAzure.Storage.Table.TableQuery<TElement>,
Microsoft.WindowsAzure.Storage.Table.TableRequestOptions,
Microsoft.WindowsAzure.Storage.OperationContext)'
TableEntity clearly has a public parameterless constructor and is non-abstract. The following is the object from metadata info when I hit F12 on TableEntity (just to ensure its resolving the TableEntity type correctly).
namespace Microsoft.WindowsAzure.Storage.Table
{
public class TableEntity : ITableEntity
{
// Summary:
// Initializes a new instance of the Microsoft.WindowsAzure.Storage.Table.TableEntity
// class.
public TableEntity();
...
}
}
Any ideas anyone? FYI I'm using Azure Client library 3.0.1.0.
UPDATE: Added linked issue which solved a similar problem
Upvotes: 3
Views: 1452
Reputation: 882
So turns out that if a method provides a constraint on type, that constraint must be also forwarded by any callers of that type.
I didn't know that.
In this case the definition for Table.ExecuteQuery looks like the following
public IEnumerable<TElement> ExecuteQuery<TElement>(TableQuery<TElement> query,
TableRequestOptions requestOptions = null,
OperationContext operationContext = null)
where TElement : ITableEntity, new();
Therefore adding new() to my constraints for T fixes the issue.
So the final method declaration looks like
internal static IEnumerable<T> GetEntitiesWithCommaSeparatedRowKeys<T>(string tableName,
string partitionKey,
string commaDelimitedStringOfRowKeys)
where T : TableEntity , new() //This is new (pun intended :))
Found a related issue in one of the related links that showed up for this question.
I'm guessing the compiler could always look up the type constraints from when I actually make the call, but since TableEntity is public (and not sealed) I guess it could end up being a runtime issue.
Also interesting to note that my method is marked internal which should really enable the compiler to check against callers within the library.
Anyways, learnt something new :).
Upvotes: 10