这是我偶然发现的事情,能够以某种方式解决它。但是现在它回来了,依赖于我的好奇心 - 我很想得到明确的答案。
基本上,我有一个通用的dgv BaseGridView<T> : DataGridView where T : class
。基于BaseGridView
的构造类型(例如InvoiceGridView : BaseGridView<Invoice>
)稍后在应用程序中使用BaseGridView
提供的共享功能来显示不同的业务对象(如虚拟模式,按钮等)。 )。
现在有必要创建一个引用这些构造类型的用户控件来控制BaseGridView
中的一些 共享 功能(例如过滤)。因此,我希望在用户控件上创建一个公共属性,使我能够将它附加到Designer /代码中的任何BaseGridView
:public BaseGridView<T> MyGridView { get; set; }
。问题是,它不起作用:-)编译时,我收到以下消息:
找不到类型或命名空间名称“T”(您是否缺少using指令或程序集引用?)
我意识到我可以将共享功能提取到接口,将BaseGridView
标记为实现该接口,然后在我的uesr控件中引用创建的接口。
但我很好奇是否存在一些神秘的C#命令/语法可以帮助我达到我想要的效果 - 而不用我真正不需要的界面来污染我的解决方案: - )
编辑:作为参考,我确实尝试了这种无辜的解决方法:BaseGridView<object> MyGridView { get; set; }
,并且......它仍然不是答案:无法隐式转换类型'InvoiceGridView'到'BaseGridView&lt; object&gt;'。
好的,因为协方差只在接口上支持,我承认失败并定义了一个接口(只显示了一些):
public interface IBaseGridView<out T> where T : class
{
bool ScrollTo(Predicate<T> criteria);
bool ScrollTo(T object);
}
我现在能够将我心爱的InvoiceGridView
投射到一个IBaseGridView<object>
- 这很棒,我又是一个快乐的男孩:-)然而,第二个{ {1}}在编译时给我带来麻烦:
无效方差:类型参数“T”在'GeParts.Controls.IBaseGridView.ScrollTo(T)'上必须是违反有效的。 'T'是协变的。
我现在必须将签名修改为ScrollTo
- 这不是理想的,但可以完成工作。令我感到惊讶的是,编译器抱怨第二个ScrollTo(object o)
,但对第一个感到满意。所以似乎不允许传递ScrollTo
的实例,但是使用类型本身(例如在out T
中)可以吗?看起来相当挑剔...
答案 0 :(得分:1)
例如:
public BaseGridView<T> GetMyGridView<T>() { ... }
public void SetMyGridView<T>(T gridView) { ... }
或
class MyClass<T> {
public BaseGridView<T> MyGridView { get; set; }
}
答案 1 :(得分:1)
自从你写了
但我很好奇是否存在一些神秘的C#命令/语法可以帮助我实现我想要的目标
我想补充一点,C#4.0可以使用&lt;替换基类型的派生类型。出T&gt;为了协方差。所以你可以做到
public BaseGridView&lt; Object &gt; MyGridView {get;组; }
所以你得到一个众所周知的类型,但你可以返回你想要的任何BaseGridView。不幸的是,唯一的问题是协方差只允许在接口上使用! :(
答案 2 :(得分:0)
不应该是这样的:
public BaseGridView MyGridView {get;组; } 击>
public BaseGridView<T> GetMyGridView<T> { return whatever; }
public void SetMyGridView<T>( BaseGridView<T> bgv) { whatever = bgv; }
...
编辑。马修是对的,属性可能不是通用的。你必须使用getter / setter。
答案 3 :(得分:0)
以下可能有效:
public BaseGridView<T> MyGridView<T> { get; set; }
原始答案的问题是类型参数必须出现在方法或类声明中,而不仅仅出现在返回值上。
请注意,编译器无法从返回值推断泛型类型,因此您需要在每次调用T
时指定MyGridView
。
答案 4 :(得分:0)
我只是尝试了一些代码,它对我来说很好用:
public class A<T> where T : class
{
public virtual A<T> ARef
{
get { return default(A<T>); }
}
}
public class B : A<B>
{
public override A<B> ARef
{
get
{
return base.ARef;
}
}
}