I am aware that it's not possible to alias a generic type (e.g. using Foo = Dictionary; is invalid), but that the generic type on the right must be closed (e.g. using Foo = Dictionary<int, string>; will work).
However, it seems like it's invalid to alias an IDictionary<string, object>--instead, the alias must be for just the interface IDictionary. The error I get is "CS0308: The non-generic type 'IDictionary' cannot be used with type arguments." Is there a way to alias this entire thing? (Or a better way to achieve what I want?)
A common thing I do in my API is for functions to take an IDictionary<string, object>, and I'd like to do something akin to using ParsedObjects = IDictionary<string, object>;. In fact, I'd like to be able to declare:
using ParsedObjectsHandler = Func<Interaction, object, IDictionary<string, object>, Task>;
(But I am willing to settle for just the former.)
Edit: Although the below answer solves the question (and I'm leaving it up as I could not find the info anywhere else), I did go with V.Lion's suggestion in the comments to define my own delegate type instead.
The issue was that I was attempting to use System.Collections.IDictionary instead of System.Collections.Generic.IDictionary<TKey, TValue>. Using the latter worked just fine, i.e.:
using ParsedObjects = System.Collections.Generic.IDictionary<string, object>;
Related
I have following statement:
private delegate ITask<Id> CreateObjectDelegateAsync<in T>(T #object)
where T : Model.Object;
And I want to store that in a dictionary:
Dictionary<Type, CreateObjectDelegateAsync<Model.Object>>
Now I am getting errors since T is not covariant and he can't convert it. I have multiple delegates with a derived T that need to be inside that dictionary.
T must be invariant in order for it to be usable as a type in the parameters. Any ideas or workarounds for this?
So the solution was quite simple: While I can't do it with invariance here directly, I can just use a:
Dictionary<Type, Delegate>
instead. I can assign any delegate to that no matter the generic type. Then later when getting the delegate I will just need to cast it to
CreateObjectDelegateAsync<T>
again.
Like so (given that T is an existing type in the dictionary):
(CreateObjectDelegateAsync<T>)DelegateDictionary[typeof(T)]
See the following recent answer:
https://stackoverflow.com/a/36421418/1017882
To summarise, an extension method has been written that uses generics:
static TResult GetEntry<TEnum, TResult>(this Dictionary<TEnum, string> dictionary, TEnum key) {...}
All works fine when invoked like so:
var attributes = new Dictionary<MyTestEnum, string>();
var result = attributes.GetEntry<MyTestEnum, double>(MyTestEnum.First);
But if I invoke it differently:
var result = attributes.GetEntry(MyTestEnum.First);
Apparently the compiler can no longer infer the types. But it's very clear to see (based on what attributes is), what type I'm attempting to pass.
Why must I be explicit with what types I pass? It feels like unnecessary code.
Usually questions like this are answered with example usage that would 'break' without this kind of extra info - but I can't think of any scenarios like this.
Bit More Context
The reason I even tried drop that bit of syntax in the first place is because I (vaguely) recall being able to do so with certain generic uses. I wanted to see how it applies with collections like this.
But it's very clear to see (based on what attributes is), what type I'm attempting to pass.
But not how you are trying to pass it.
TResult does not depend on any of the types passed, so there's no way of knowing you want GetEntry<MyTestEnum, double> and not GetEntry<MyTestEnum, int> or GetEntry<MyTestEnum, MyTestEnum> or what have you.
There are times when a human using wider context than the compiler uses can see what is meant even when the compiler can't infer it, but this isn't one of those cases. I can only guess you probably want GetEntry<MyTestEnum, double> because that's the example you use earlier in your question.
If on the other hand you had something like:
public static TResult GetEntry<TKey, TResult>(Dictionary<TKey, TResult> dict, TKey key)
{
return dict[key];
}
Then because all the type parameters relate to part of the signature of what it is called with, it would indeed be inferable, though there are still subtler cases where such inference can't happen.
Hi I want to return pair of strings. I am right now using IEnumerable<Tuple<string, string>> as a return type but fxcop gives warning. I am using concurrentBag with Parallel.For so want to avoid ConcurrentDictionary<string,IList<string>> or ConcurrentDictionary<string,Concurrentbag< string>>. Also new class or struct does not make sense. What will be the proper solution.
Thanks a lot,
Omkar
If you feel the the type you're using is optimal, you should ignore / suppress the warning.
However, you should probably replace the Tuple<string, string> with a custom class that has meaningful property names.
foreach (Pair<Pair<int, int>, Cell> cell in sheet.Cells)
{
dgvCells[cell.Left.Right, cell.Left.Left].Value = cell.Right.Value;
}
I am working on creating a excel file from within .NET, using this Excel Library
I am getting the warning mentioned in the title. Any ideas?
Just for future reference, and understanding, the error message:
The non-generic type '' cannot be used with type arguments
is replaced with some class, indicates that within your code you are attempting to make use of a non-generic class in a generic way. More specifically you are using some syntax which is incompatible with that type, in this case the <> generic braces on the type "Pair".
To typically solve the problem
Identify the types use within the file, specifically its use in a generic way. (This should find them: Ctrl + F > "SomeClass<")
Ensure that the type is as expected (F12 on the type should take you to its declaration)
If the type is different to the expected type you should make use of a using alias to point to the correct type namespace i.e.
using Pair = Fully.Qualified.Namespace.Of.Pair;
If the type is as expected ensure that it is generic, if not you can either modify it to be generic, if you have permission/access to do so, or you could select/create a different type which is more suitable for your purpose.
Alternativly you could modify your use of the type to be non-generic
It means that Pair in the code above is referring to System.Web.UI.Pair instead of some other "pair" class such as System.Collections.Generic.KeyValuePair (which is generic).
Depending on which Pair the above code was meant to instantiate, use something like
using Pair = MyNamespace.Pair;
to resolve the issue (this example assumes you really want to use MyNamespace.Pair).
Update:
It seems that in your case the exact solution is
using Pair = QiHe.CodeLib.Pair;
Because MSDN provides the Pair definition as:
[SerializableAttribute]
public sealed class Pair
There is not a definition that includes Pair<T1, T2>. If there is another Pair class, you need to include that namespace in your 'using' clause.
I'm trying to convert a Dictionary< dynamic, dynamic > to a statically-typed one by examining the types of the keys and values and creating a new Dictionary of the appropriate types using Reflection. If I know the key and value types, I can do the following:
Type dictType = typeof(Dictionary<,>);
newDict = Activator.CreateInstance(dictType.MakeGenericType(new Type[] { keyType, valueType }));
However, I may need to create, for example, a Dictionary< MyKeyType, dynamic > if the values are not all of the same type, and I can't figure out how to specify the dynamic type, since
typeof(dynamic)
isn't viable.
How would I go about doing this, and/or is there a simpler way to accomplish what I'm trying to do?
The C# compiler emits System.Object as the type for "dynamic". "dynamic" is a language-specific construct and has no corresponding type in the Common Language Infrastructure. As such, you won't be able to use reflection to create a "dynamic" nor use "dynamic" as a generic type parameter.
A Dictionary<dynamic, dynamic> is really a Dictionary<object, object>. What "dynamic" means to the compiler is simply late-bind any member accesses for the object using reflection (the implementation of which lies in the Microsoft.CSharp assembly in case you're curious).
On a side note, the compiler will also emit an attribute, DynamicAttribute, on fields, parameters, etc. that are "dynamic"; that allows people consuming the assembly's metadata to distinguish between a System.Object and a "dynamic". This is how IntelliSense shows a method's parameter as dynamic from an assembly reference, for example.
Dictionary<MyType, Object>
Activator.CreateInstance(typeof (Dictionary<dynamic, dynamic>));
This actually creates a Dictionary<Object, Object>
The only use I can see from using dynamic instead of object is during code typing you can use dic["some"].MyDynProperty.... but if you create you object with Activator it will return Object so no use in code typing...