C# 使用两个泛型类型参数推断泛型类型
我有以下方法C# 使用两个泛型类型参数推断泛型类型,c#,generics,type-inference,C#,Generics,Type Inference,我有以下方法 public bool HasTypeAttribute<TAttribute, TType>(TType obj) { return typeof(TType).GetCustomAttribute<TAttribute>() != null; } 而不是 Foo.Demo<Bar>(new Bar()); Foo.Demo(新条()); 那么,在这种情况下,有没有一种方法可以使类型推断工作?这是我的设计缺陷还是我能实现我想要的?
public bool HasTypeAttribute<TAttribute, TType>(TType obj)
{
return typeof(TType).GetCustomAttribute<TAttribute>() != null;
}
而不是
Foo.Demo<Bar>(new Bar());
Foo.Demo(新条());
那么,在这种情况下,有没有一种方法可以使类型推断工作?这是我的设计缺陷还是我能实现我想要的?对参数重新排序也没有帮助…因为C#规则不允许这样做
对于C#来说,有一个规则是可行的,如果某些类型与参数相关(因此至少在某些时候可以推断),并且显式给定类型的数量与剩余的不可推断类型的数量相同,那么这两个类型将协同工作
这需要有人提出,说服其他参与C#周围决策的人,这是一个好主意,然后付诸实施。但这并没有发生
除了特性一开始就必须证明自己值得它们带来的额外复杂性之外(在语言中添加任何东西,随着工作量的增加,它会立即变得更复杂,编译器出现错误的机会也会增加等等),问题是,这是个好主意吗
另外,您在这个特定示例中的代码会更好
相反,现在每个人的代码都稍微复杂一些,因为有更多的错误可能是错误的,导致代码在运行时而不是编译时失败,或者错误消息不太有用
人们已经发现一些关于推理的案例令人困惑,这表明增加另一个复杂的案例是没有帮助的
这并不是说这绝对是一个坏主意,只是说它的优点和缺点使它成为一个意见问题,而不是一个明显的缺陷。您可以将调用分为多个步骤,这样就可以让类型推断在任何可能的地方发挥作用
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);
公共类类型帮助器
{
public bool HasTypeAttribute(),其中tatAttribute:Attribute
{
返回typeof(TType).GetCustomAttribute()!=null;
}
}
公共静态类TypeHelper
{
用于(此T对象)的公共静态类型帮助器
{
返回新的TypeHelperFor();
}
}
//理想,但没有得到支持
HasTypeAttribute(实例);
//锁链
例如.hastypetAttribute();
//直接向前/非链式
HasTypeAttribute(实例);
对于这种情况,这应该是可行的,但我警告不要在最终方法返回void的情况下使用它,因为如果不使用返回值,很容易留下半链
e、 g
//如果我忘了在这里完成链。。。
if(TypeHelper.For(instance))//编译器错误
//但如果我忘记了上一次关于副作用的电话,比如:
//DbHelper.For(table.Execute();
DbHelper.For(表);//幸福地编译,但什么也不做
//而非链接版本可以保护我
DbHelper.Execute(表);
您只需传入一个对象
,然后使用obj.GetType
而不是typeof(TType)
@juharr,这样做不会得到相同的结果。@JonHanna为什么不呢?如果对象的类型与泛型类型相同,那么它应该可以工作。@ThomasFlinkow我的意思是您将拥有公共bool HasTypeAttribute(object obj)
。基本上它不能做parial泛型推断。它必须推断出所有对象,或者必须指定所有对象。@juharr,如果对象与泛型类型不同,则其工作方式会有所不同。只有当对象的实际具体类型(object.GetType()
)与编译器从中推断的表达式类型匹配时,它们才会相同,如果该类型是基类型或接口,则情况就不会相同。
public void Demo<T>(T obj)
{
}
Foo.Demo(new Bar());
Foo.Demo<Bar>(new Bar());
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);
// 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);