Infer generic type with two generic type parameters [duplicate]

假如想象 提交于 2021-02-05 05:23:32

问题


I have the following method

public bool HasTypeAttribute<TAttribute, TType>(TType obj)
{
    return typeof(TType).GetCustomAttribute<TAttribute>() != null;
}

and I want to be able to use it like this:

MyClass instance = new MyClass();

TypeHelper.HasTypeAttribute<SerializableAttribute>(instance);

but I can't get it working because of the

incorrect number of type parameters

so that I need to call

TypeHelper.HasTypeAttribute<SerializableAttribute, MyClass>(instance);

which certainly makes sense, but why can the compiler not infer the type of the passed object? Because if the method looked like this:

public void Demo<T>(T obj)
{
}

the compiler would certainly be able to infer the type, so that I can write

Foo.Demo(new Bar());

instead of

Foo.Demo<Bar>(new Bar());

So, is there a way to make type inference work in this case? Is it a design flaw by me or can I achieve what I want? Reordering the parameters doesn't help too...


回答1:


Because the C# rules don't allow that.

It would be feasible for C# to have a rule where if some of the types related to parameters (and hence could be inferred at least some of the time) and the number of explicitly given types was the same as the number of remaining un-inferrable types, then the two would work in tandem.

This would need someone to propose it, convince other people involved in the decision-making around C# it was a good idea, and then for it to be implemented. This has not happened.

Aside from the fact that features start off having to prove themselves worth the extra complexity they bring (add anything to a language and it is immediately more complex with more work, more chance of compiler bugs etc.) the question then is, is it a good idea?

On the plus, your code in this particular example would be better.

On the negative, everyone's code is now slightly more complicated, because there's more ways something that is wrong can be wrong, resulting either in code that fails at runtime rather than compile-time or less useful error messages.

That people already find some cases around inference to be confusing would point to the idea that adding another complicating case would not be helpful.

Which isn't to say that it is definitely a bad idea, just that there are pros and cons that make it a matter of opinion, rather than an obvious lack.




回答2:


You could break the call into multiple steps, which lets type inference kick in wherever it can.

public class TypeHelperFor<TType>
{
    public bool HasTypeAttribute<TAttribute>() where TAttribute : Attribute
    {
        return typeof(TType).GetCustomAttribute<TAttribute>() != null;
    }
}

public static class TypeHelper
{
    public static TypeHelperFor<T> For<T>(this T obj)
    {
        return new TypeHelperFor<T>();
    }
}

// The ideal, but unsupported
TypeHelper.HasTypeAttribute<SerializableAttribute>(instance);
// Chained
TypeHelper.For(instance).HasTypeAttribute<SerializableAttribute>();
// Straight-forward/non-chained
TypeHelper.HasTypeAttribute<SerializableAttribute, MyClass>(instance);

That should work alright for this case, but I'd warn against using it in cases where the final method returns void, because it's too easy to leave the chain half-formed if you're not doing anything with the return value.

e.g.

// If I forget to complete the chain here...
if (TypeHelper.For(instance)) // Compiler error

// But if I forget the last call on a chain focused on side-effects, like this one:
// DbHelper.For(table).Execute<MyDbOperationType>();
DbHelper.For(table); // Blissfully compiles but does nothing

// Whereas the non-chained version would protect me
DbHelper.Execute<MyTableType, MyDbOperationType>(table);


来源:https://stackoverflow.com/questions/48322044/infer-generic-type-with-two-generic-type-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!