假设你有一个非泛型Foo和泛型类Foo。在非泛型类中,有一个非泛型FooBar类型的成员变量,同样,在泛型类中有一个类型为FooBar的成员变量。
public class Foo
{
protected FooBar SomeVar;
public void DoSomething()
{
// Manipulate SomeVar here
}
}
public class Foo<T>: Foo where T: SomeObject
{
protected new FooBar<T> SomeVar;
}此外,FooBar是从FooBar派生的,这在代码中没有显示出来。
假设在非泛型类中有一个方法,它对成员变量SomeVar执行一些数据操作。现在的问题是,如果实例化了泛型类Foo,则在非泛型类中实现的方法只引用非泛型SomeVar,而不了解泛型变量。
现在,解决这个问题的唯一方法似乎是覆盖泛型类中的DoSomething方法,这将允许它了解泛型变量。
我猜这种方法的问题是逻辑从非泛型类复制到泛型类。这个问题有什么替代方案吗?
更新:我已经更新了类,使其更符合我的问题:
public abstract class BaseObject
{
// Abstract class that handles how the object is loaded when querying database for an object
}
public class Name : BaseObject
{
public string FirstName {get;set;}
public string LastName {get;set;}
public Date DOB {get;set;}
}
public interface IData
{
List<string> SearchFields;
string timestamp;
Search search; // Search is a class that will query the database for a given object and because this is a non generic version, it'll bring back a list of base object
}
public interface IData<T> : IData, where T: BaseObject
{
Search<T> search; // Bring back a list of <T>
}
public class BrowseData: IData
{
Search search;
}
public class BrowseData<T>: BrowseData, IData<T> where T: BaseObject
{
Search<T> search;
}
public class BrowseBuilder
{
protected BrowseData Data;
public BrowseBuilder(BrowseData data)
{
Data = data;
}
public void DoRender()
{
// Using the data provided does the rendering
}
}
public class BrowseBuilder<T>: BrowseBuilder where T: BaseObject
{
protected new BrowseData<T> Data;
public BrowseBuilder(BrowseData<T> data)
{
Data = data;
}
}我的问题是在非泛型类BrowseBuilder中实现的DoRender方法,它使用非泛型数据/搜索来执行呈现,该呈现将返回baseObject列表,而泛型版本将返回T列表。
也许我看错了,搜索应该是非泛型的,不管怎样,操作它的基方法应该返回baseObject的列表。
发布于 2014-03-10 22:10:08
下面是一个使用接口的解决方案:
public interface IFooBar
{
// methods used for modifications
}
public class FooBar : IFooBar
{
// implement modification methods
}
public class FooBar<T> : IFooBar where T : SomeClass
{
// implement modification methods
}
public class Foo
{
protected IFooBar SomeVar;
public void DoSomething()
{
// Manipulate SomeVar via IFooBar interface here
}
}
public class Foo<T>: Foo where T: SomeObject
{
}这看起来像是我在转移问题,但如果FooBar和FooBar<T>没有公共接口,您无论如何都需要为它们实现不同的修改代码。
发布于 2014-03-10 22:08:27
它并不美观,但它完成了任务:您可以在基类中定义一个事件来公开SomeVar中的值更改,并相应地更新派生类中的属性。反之亦然。这意味着FooBar<T>是从FooBar派生的,这在您的代码中没有显示出来。
public class Foo {
private FooBar _someVar;
protected FooBar SomeVar {
get { return _someVar; }
set {
if (_someVar != value) {
_someVar = value;
OnSomeVarUpdated();
}
}
}
protected event EventHandler SomeVarUpdated;
private void OnSomeVarUpdated() {
var someVarUpdated = SomeVarUpdate;
if (someVarUpdated != null) {
someVarUpdated(this, EventArgs.Empty);
}
}
public virtual void DoSomething() {
// Manipulate SomeVar here
var someVar = ....;
SomeVar = someVar;
}
}
public class Foo<T>: Foo where T: SomeObject {
public Foo() {
OnSomeVarUpdated += () => {
// Pull new value from base
SomeVar = (FooBar<T>)base.SomeVar;
};
}
private FooBar<T> _someVar;
protected new FooBar<T> SomeVar {
get { return _someVar; }
set {
if (_someVar != value) {
_someVar = value;
// Push new value to base
base.SomeVar = value;
}
}
}
}发布于 2014-03-10 23:43:18
就我个人而言,我会根据上下文、情况和你需要它的目的来选择不同的方法。对于所描述的问题,没有通用的解决方案。提供更多上下文详细信息将有助于提供更准确的答案。
如果你想要其他的选择,下面是:
FooBar类。直接或通过接口视情况而定。然后您的Foo将拥有DoSomething()代理,它将直接在实际的FooBar实例上调用实际的方法。FooBar是没有上述逻辑解决方案的简单的get/set类,则会打破这种模式。要克服此问题,请创建另一个用于继承操作的类,该类将实现所需的继承( methods.Foo : Foo<SomeClass>,而不是Foo<T> : Foo。但要注意-当类是为了进一步继承时,事情可能会变得混乱。此外,此解决方案并不适用于所有情况。这非常轻微地触及了covariance/contravariance主题。脚注
此外,我建议不要使用将protected FooBar SomeVar与其他成员一起隐藏在Foo<T>中,除非它是性能关键型的。相反,在Foo<T>中使用属性和属性将只从基类返回强制转换的值。通过这种方式,你将在基类中只有一个成员。在FooBar.SomeVar和FooBar<T>.SomeVar中不可能有不同的值。
https://stackoverflow.com/questions/22302095
复制相似问题