Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# c语言中减少代码复制的惯用方法# 我是C语言中的新成员(我来自C++),我面对一个简单的模式,C++中我会用模板来解决,但是同样的方法不能用C语言泛型。 下一个代码(C++与C++模板的混合)显示了我的问题。 class A { /* ... */ } class B { /* ... */ } // C, D, ... class W { public void Update(A a) { /* ... */ } public void Update(B b) { /* ... */ } // C, D, ... } class X { template <typename T> public void Update(IEnumerable<T> vs) { if (vs.any(vs => CreateOrUpdate(v))) { doStuff(); } } template <typename T> public void Update(T v) { if (CreateOrUpdate(v)) { doStuff() } } template <typename T> private bool CreateOrUpdate(T v) { W w; bool updated = false; if (!m.TryGetValue(v.Id, out w)) { w = new W(v.Id); m.Add(w.Id, w); updated = true; } return w.Update(v) || updated; } private Dictionary<string, W> m; } A类{/*…*/} B类{/*…*/} //C,D。。。 W类 { 公共无效更新(A){/*…*/} 公共无效更新(B){/*…*/} //C,D。。。 } X类 { 模板 公共无效更新(IEnumerable vs){ 如果(vs.any(vs=>CreateOrUpdate(v))){ doStuff(); } } 模板 公共无效更新(TV) { 如果(创建或更新(v)){ 多斯塔夫() } } 模板 私有布尔CreateOrUpdate(电视) { W; bool updated=false; 如果(!m.TryGetValue(v.Id,out w)){ w=新w(v.Id); m、 添加(w.Id,w); 更新=真; } 返回w.Update(v)| | updated; } 私人词典m; }_C#_Templates_Generics_Design Patterns - Fatal编程技术网

C# c语言中减少代码复制的惯用方法# 我是C语言中的新成员(我来自C++),我面对一个简单的模式,C++中我会用模板来解决,但是同样的方法不能用C语言泛型。 下一个代码(C++与C++模板的混合)显示了我的问题。 class A { /* ... */ } class B { /* ... */ } // C, D, ... class W { public void Update(A a) { /* ... */ } public void Update(B b) { /* ... */ } // C, D, ... } class X { template <typename T> public void Update(IEnumerable<T> vs) { if (vs.any(vs => CreateOrUpdate(v))) { doStuff(); } } template <typename T> public void Update(T v) { if (CreateOrUpdate(v)) { doStuff() } } template <typename T> private bool CreateOrUpdate(T v) { W w; bool updated = false; if (!m.TryGetValue(v.Id, out w)) { w = new W(v.Id); m.Add(w.Id, w); updated = true; } return w.Update(v) || updated; } private Dictionary<string, W> m; } A类{/*…*/} B类{/*…*/} //C,D。。。 W类 { 公共无效更新(A){/*…*/} 公共无效更新(B){/*…*/} //C,D。。。 } X类 { 模板 公共无效更新(IEnumerable vs){ 如果(vs.any(vs=>CreateOrUpdate(v))){ doStuff(); } } 模板 公共无效更新(TV) { 如果(创建或更新(v)){ 多斯塔夫() } } 模板 私有布尔CreateOrUpdate(电视) { W; bool updated=false; 如果(!m.TryGetValue(v.Id,out w)){ w=新w(v.Id); m、 添加(w.Id,w); 更新=真; } 返回w.Update(v)| | updated; } 私人词典m; }

C# c语言中减少代码复制的惯用方法# 我是C语言中的新成员(我来自C++),我面对一个简单的模式,C++中我会用模板来解决,但是同样的方法不能用C语言泛型。 下一个代码(C++与C++模板的混合)显示了我的问题。 class A { /* ... */ } class B { /* ... */ } // C, D, ... class W { public void Update(A a) { /* ... */ } public void Update(B b) { /* ... */ } // C, D, ... } class X { template <typename T> public void Update(IEnumerable<T> vs) { if (vs.any(vs => CreateOrUpdate(v))) { doStuff(); } } template <typename T> public void Update(T v) { if (CreateOrUpdate(v)) { doStuff() } } template <typename T> private bool CreateOrUpdate(T v) { W w; bool updated = false; if (!m.TryGetValue(v.Id, out w)) { w = new W(v.Id); m.Add(w.Id, w); updated = true; } return w.Update(v) || updated; } private Dictionary<string, W> m; } A类{/*…*/} B类{/*…*/} //C,D。。。 W类 { 公共无效更新(A){/*…*/} 公共无效更新(B){/*…*/} //C,D。。。 } X类 { 模板 公共无效更新(IEnumerable vs){ 如果(vs.any(vs=>CreateOrUpdate(v))){ doStuff(); } } 模板 公共无效更新(TV) { 如果(创建或更新(v)){ 多斯塔夫() } } 模板 私有布尔CreateOrUpdate(电视) { W; bool updated=false; 如果(!m.TryGetValue(v.Id,out w)){ w=新w(v.Id); m、 添加(w.Id,w); 更新=真; } 返回w.Update(v)| | updated; } 私人词典m; },c#,templates,generics,design-patterns,C#,Templates,Generics,Design Patterns,即使A,B,…实现像interface IId{string Id{get;}}这样的接口,并且我使用泛型public void Update(IEnumerable vs):其中T:IId,由于w.Update(v)(需要添加public bool Update(IId))W中的,但此方法将始终被调用) 从理论的角度理解C泛型与C++模板的区别,以及为什么代码> W.Update(V)< /C>不能静态地从 W > 更新>代码>方法之间调用。但是,我无法找出解决此问题的最佳方法。一种方法确实是

即使
A,B,…
实现像
interface IId{string Id{get;}}
这样的接口,并且我使用泛型
public void Update(IEnumerable vs):其中T:IId
,由于
w.Update(v)
(需要添加
public bool Update(IId))
W
中的
,但此方法将始终被调用)


从理论的角度理解C泛型与C++模板的区别,以及为什么代码> W.Update(V)< /C>不能静态地从<代码> W<代码> > <代码>更新>代码>方法之间调用。但是,我无法找出解决此问题的最佳方法。

一种方法确实是向类
W
添加一个方法
public bool Update(IId id)
,但您需要动态调度参数
id

class W
{
    public bool Update(IId id)
    {
        dynamic d_id = id;
        return Update(d_id);
    }

    // ...
}
程序将在运行时确定调用哪个
Update
函数,因为
d_id
被声明为
dynamic

如果您添加另一个实现
IId
的类
E
,但忘记实现
Update(ee)
,则上述
Update
函数将递归调用其自身,直到内存不足。通过将
Update(IId id)
重命名为
DoUpdate(IId id)
并在
CreateOrUpdate
中调用
DoUpdate,可以避免无限递归的危险。然后,您将得到一个有意义的异常,说明类型为
E
id
无法调度


MSDN上有一个很好的答案可能会对您有所帮助。

可能会有更好的答案,但以下是我的看法

假设
A
B
都实现了包含属性
Id
的接口
IId
。我将在这些类中要实现的接口中添加一个方法
Update(W)
,这样您可以编写:

private bool CreateOrUpdate(T v)
{
    W w;
    bool updated = false;
    if (!m.TryGetValue(v.Id, out w)) {
        w = new W(v.Id);
        m.Add(w.Id, w);
        updated = true;
    }
    return v.Update(w) || updated;
}
这样,您就可以对每种情况都一视同仁,这基本上就是接口的要点(而不是玩弄
typeof
开关和糟糕的性能反射)。在我看来,这是解决问题的更好的面向对象方法。这被称为

顺便说一下,你可以写:

 class X<T> where T : IId
X类,其中T:IId

而不是编写泛型方法(类将变为泛型而不是其方法)。它必须在语义上有意义,因此我无法真正区分您的具体情况(类名被混淆)。

请将问题标记为适当的-是C#问题吗?是的。实际上,它被标记为c。(我不知道你的意思)是C++吗?如果没有,请删除标记。您的意思是:但是,此方法将始终被调用?但是,如果您希望减少代码重复,您不应该更喜欢在
W
中使用单个
更新(IId id)
方法吗?或者
更新(T id),其中T:IId
?谢谢。我认为在一个类似的解决方案中使用多态性,但没有你的优雅。我假设没有办法避免运行时检查,对吗?您可以实现访问者模式,如下所示。IMHO,访问者模式一点也不优雅,因为它只是一种手动实现动态调度的侵入性方式。这是我提出的解决方案,但正如您所说,在我的案例A中,B。。。不应该知道W。对不起,你能确认没有运行时检查就没有解决方案吗?在运行时解决这个问题类似于强制转换,你不知道它是否能工作,直到你实际运行你的应用程序,并且你有可能遇到运行时异常(或者更糟糕的是,在这种情况下,堆栈溢出)。我会避免这种情况,因为您失去了类型安全性,而且它确实表明存在代码气味。@Groo,我有什么选择?如果我希望代码是类型安全的,避免代码重复,我可以只添加“public void W::Update(A){genericUpdate(A);}”,并将genericUpdate设置为private。
Update(W)
的主体应该是
W.Update(this)
,我想?因此,您的方法通常被称为visitor或double dispatch模式,这是一种手动实现动态调度的方法(以类型安全的方式授予);这要视情况而定。我想说,这两种方法都是合理的:)我同意。有时我倾向于使用这两种模式。