首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在泛型/非泛型情况下操作类成员

在泛型/非泛型情况下操作类成员
EN

Stack Overflow用户
提问于 2014-03-10 21:52:17
回答 3查看 89关注 0票数 1

假设你有一个非泛型Foo和泛型类Foo。在非泛型类中,有一个非泛型FooBar类型的成员变量,同样,在泛型类中有一个类型为FooBar的成员变量。

代码语言:javascript
复制
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方法,这将允许它了解泛型变量。

我猜这种方法的问题是逻辑从非泛型类复制到泛型类。这个问题有什么替代方案吗?

更新:我已经更新了类,使其更符合我的问题:

代码语言:javascript
复制
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的列表。

EN

回答 3

Stack Overflow用户

发布于 2014-03-10 22:10:08

下面是一个使用接口的解决方案:

代码语言:javascript
复制
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
{

}

这看起来像是我在转移问题,但如果FooBarFooBar<T>没有公共接口,您无论如何都需要为它们实现不同的修改代码。

票数 1
EN

Stack Overflow用户

发布于 2014-03-10 22:08:27

它并不美观,但它完成了任务:您可以在基类中定义一个事件来公开SomeVar中的值更改,并相应地更新派生类中的属性。反之亦然。这意味着FooBar<T>是从FooBar派生的,这在您的代码中没有显示出来。

代码语言:javascript
复制
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;
            }
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2014-03-10 23:43:18

就我个人而言,我会根据上下文、情况和你需要它的目的来选择不同的方法。对于所描述的问题,没有通用的解决方案。提供更多上下文详细信息将有助于提供更准确的答案。

如果你想要其他的选择,下面是:

  • 将逻辑移至FooBar类。直接或通过接口视情况而定。然后您的Foo将拥有DoSomething()代理,它将直接在实际的FooBar实例上调用实际的方法。
  • 如果FooBar是没有上述逻辑解决方案的简单的get/set类,则会打破这种模式。要克服此问题,请创建另一个用于继承操作的类,该类将实现所需的继承( methods.
  • Reverse )。将其设置为Foo : Foo<SomeClass>,而不是Foo<T> : Foo。但要注意-当类是为了进一步继承时,事情可能会变得混乱。此外,此解决方案并不适用于所有情况。这非常轻微地触及了covariance/contravariance主题。

脚注

此外,我建议不要使用protected FooBar SomeVar与其他成员一起隐藏在Foo<T>中,除非它是性能关键型的。相反,在Foo<T>中使用属性和属性将只从基类返回强制转换的值。通过这种方式,你将在基类中只有一个成员。在FooBar.SomeVarFooBar<T>.SomeVar中不可能有不同的值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22302095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档