C# 我可以将泛型设置为可选,默认设置为某个类吗?
我的问题与有关,但使用内部泛型类,这种方法不起作用 给定如下代码:C# 我可以将泛型设置为可选,默认设置为某个类吗?,c#,generics,.net-3.5,C#,Generics,.net 3.5,我的问题与有关,但使用内部泛型类,这种方法不起作用 给定如下代码: using System; public class FooEventArgs<T> : EventArgs { // ... T properties and a constructor } public class Foo<T> { public delegate void EventHandler<FooEventArgs>(object sender, FooEve
using System;
public class FooEventArgs<T> : EventArgs
{
// ... T properties and a constructor
}
public class Foo<T>
{
public delegate void EventHandler<FooEventArgs>(object sender, FooEventArgs<T> e);
public event EventHandler<FooEventArgs<T>> Changed
}
public class User
{
public Foo<int> foo1;
public Foo<object> foo2;
public User()
{
foo1 = new Foo<int>();
foo2 = new Foo<object>();
foo1.Changed += foo1_Changed;
foo2.Changed += foo2_Changed;
}
protected void foo1_Changed(object sender, FooEventArgs<int> e) { ... }
protected void foo2_Changed(object sender, FooEventArgs<object> e) { ... }
}
public class User
{
public Foo foo3;
public User()
{
foo3 = new Foo();
foo3.Changed += foo3_Changed;
}
protected void foo3_Changed(object sender, FooEventArgs e) { ... }
}
然后我想这样使用它:
using System;
public class FooEventArgs<T> : EventArgs
{
// ... T properties and a constructor
}
public class Foo<T>
{
public delegate void EventHandler<FooEventArgs>(object sender, FooEventArgs<T> e);
public event EventHandler<FooEventArgs<T>> Changed
}
public class User
{
public Foo<int> foo1;
public Foo<object> foo2;
public User()
{
foo1 = new Foo<int>();
foo2 = new Foo<object>();
foo1.Changed += foo1_Changed;
foo2.Changed += foo2_Changed;
}
protected void foo1_Changed(object sender, FooEventArgs<int> e) { ... }
protected void foo2_Changed(object sender, FooEventArgs<object> e) { ... }
}
public class User
{
public Foo foo3;
public User()
{
foo3 = new Foo();
foo3.Changed += foo3_Changed;
}
protected void foo3_Changed(object sender, FooEventArgs e) { ... }
}
问题是,它自然无法与foo3_Changed
接受FooEventArgs
;它需要FooEventArgs
,因为Foo.Changed
事件将传递给它(因为值将来自Foo
)
不幸的是,这似乎不起作用,尽管我不太清楚原因:
EditBuffer.cs(13,37): error CS0553: 'FooLibrary.FooEventArgs.implicit operator FooLibrary.FooEventArgs(FooLibrary.FooEventArgs<object>)': user-defined conversions to or from a base class are not allowed
EditBuffer.cs(13,37):错误CS0553:“愚库.FooEventArgs.implicit运算符愚库.FooEventArgs(愚库.FooEventArgs)”:不允许与基类进行用户定义的转换
那么,再一次,我能做些什么吗?或者我认为这很不幸,我只能满足于使用
FooEventArgs
(然后我想我也可以只使用Foo
)?老实说,我认为你对此无能为力。您可以使Foo
双重通用:
public class Foo<TData, TArgs> where TArgs : FooEventArgs<TData>
{
public delegate void EventHandler<TArgs>(object sender, TArgs e);
public event EventHandler<TArgs> Changed;
}
公共类Foo,其中targets:FooEventArgs
{
公共委托void EventHandler(对象发送方,目标);
公共事件事件处理程序已更改;
}
然后你可以写:
public class Foo : Foo<object, FooEventArgs>
公共类Foo:Foo
。。。但这真的让事情变得非常复杂,几乎没有什么好处
我还想说,尽管包含类型参数有点冗长,但它确实非常清楚——而继承可能会以各种方式搅乱局面。当您没有真正尝试建模行为专门化时,我会避开类继承
顺便说一下,隐式转换不起作用的原因与泛型无关——正如错误消息所述,您不能声明继承层次结构上下的转换(隐式或显式)。根据C#规范第6.4.1节:
C#只允许声明某些用户定义的转换。特别是,无法重新定义已存在的隐式或显式转换
(有关详细信息,请参见该部分。)
作为补充说明,我发现对于泛型使用继承的方式更为常见,通常是使用接口:
public interface IFoo
{
// Members which don't depend on the type parameter
}
public interface IFoo<T> : IFoo
{
// Members which all use T
}
公共接口IFoo
{
//不依赖于类型参数的成员
}
公共接口IFoo:IFoo
{
//所有使用T的成员
}
这样代码就可以只接收一个IFoo
,而不必担心泛型方面的问题,如果他们不需要知道t
不幸的是,这对您的具体情况没有帮助。我刚刚发现的另一件有趣的事情是,您可以创建具有相同名称但不同签名的泛型类
class Foo<T> {
}
class Foo<T,T> {
}
class Foo{
}
类Foo{
}
然后,您可以按如下方式调用其中一个:
new Foo<string>();
new Foo<int,double>();
new Foo<string,int>();
newfoo();
新Foo();
新Foo();
我只是觉得有趣的是,尽管两个类有相同的名称,但它们可以共存,因为它们有不同的签名
我想这就是Tuple类的工作原理
公共类元组
{
...
这是一个关于处理接口继承的相反方式的有趣见解。但正如您所观察到的,这在这种情况下是不行的。谢谢。@ChrisMorgan:是的-我只是把它作为一个次要问题提出来。我用另一个想法编辑了答案的开头,但它不是我真正喜欢的。不,我也不喜欢它……那么,明确地说我想是的。乔恩总是回答得很好。回答得很好。这和重载方法很相似work@mojoblanco在班级层面上也是如此。