Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/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
C# 我可以用C语言将组合和继承与接口结合起来吗#_C#_C# 4.0 - Fatal编程技术网

C# 我可以用C语言将组合和继承与接口结合起来吗#

C# 我可以用C语言将组合和继承与接口结合起来吗#,c#,c#-4.0,C#,C# 4.0,我有一个设计问题,我想不出来。以下是我得到的: 通常,我有两种类型的对象和选项。这些被抽象为两个接口IStrike和IOption 假设IOption有以下字段,实际上大约是10倍,但我们可以使用以下三个字段来说明问题 interface IOption { double Bid{get;set;} double Ask{get;set;} double ImpliedVol{get;set;} } interface IStrike { IOption Call{g

我有一个设计问题,我想不出来。以下是我得到的:

通常,我有两种类型的对象和选项。这些被抽象为两个接口IStrike和IOption

假设IOption有以下字段,实际上大约是10倍,但我们可以使用以下三个字段来说明问题

interface IOption
{
   double Bid{get;set;}
   double Ask{get;set;}
   double ImpliedVol{get;set;}
}


interface IStrike
{
   IOption Call{get;set;}
   IOption Put{get;set;}
}
现在,这一切都很好,但假设我有下面的方法来对IOption执行一些“数学”运算

public double SquareImpliedVol(IOption opt)
{
   return Math.Pow(opt.ImpliedVol,2);
}
同样,这不是问题,但当我为测试编写一些模拟对象时,我不清楚是否需要实现Bid和Ask。我不知道,但我不知道,除非我知道SquareImpliedVol中的胆量,这意味着我正在针对代码编写测试,这很糟糕

为了解决这个问题,我可以创建另一个只包含ImpliedVol属性的接口ioptionmpliedvol,然后让IOption像这样从ioptionmpliedvol继承

interface IOption : IOptionImpliedVol
{
   double Bid{get;set;}
   double Ask{get;set;}
}
然后我们可以切换到SquareImpliedVol

public double SquareImpliedVol(IOptionImpliedVol opt)
{
   return Math.Pow(opt.ImpliedVol,2);
}
我们很好。我会写模拟对象,一切都很美好。除了……我想写一个对列表进行操作的方法,但是我需要的唯一属性是Call.ImpliedVol和Put.ImpliedVol。我想创造一些像

interface IStrikeImpliedVol
{
   IOptionImpliedVol Call;
   IOptionImpliedVol Put;
}
然后我也可以

interface IStrike : IStrikeImpliedVol
{
   IOption Call;
   IOption Put;
}

但那是不合法的。我觉得必须要有某种设计模式才能解决这个问题,但我陷入了某种组合和继承的网络中。

我认为您最初设计的两个接口是正确的。你是说你必须知道什么时候设置
Bid/Ask
,什么时候不在测试中设置,这让你很烦恼

让我们试着从另一个角度来看它。您正在为某个函数编写测试(假设它是您的
SquareImpliedVol
)。您知道,正确实现此函数应该只关心
ImpliedVol
属性,而不关心
Bid/Ask
,因此可以将这些属性留空。如果函数在未设置的情况下失败,那么您的单元测试发现了一个问题-请高兴。当然,如果空的
Bid/Ask
选项
对象的不正确状态,则它会有所不同,但在您的情况下,这似乎不是问题


换言之,我想说的是,您正在根据您的知识编写一个测试,测试特定方法应该如何工作,并且这个知识与该函数中已经编写的代码相关,这一点没有错。

有很多方法可以处理这个问题,但主要问题是您期望的解决方案是什么,不是其他人怎么处理的

例如,许多人会用模拟对象来解决“测试接受IOption对象的东西”,但他们当然不会关心实际使用了IOption的哪一部分。也就是说,这有点错误,因为如果您开始查看使用模拟库生成模拟对象的代码,他们清楚地知道使用了接口的哪一部分,因为他们将编写如下代码:

var mock = CREATE MOCK OF TYPE IOption
ON MOCK mock, EXPECT CALL TO ImpliedVol
    FOR THAT CALL, RETURN 15

test code

VERIFY THAT CALLS WERE MADE AS EXPECTED
如果您对此感到满意,我将使用一个普通的模拟库,如NMock或类似的库,为您的接口生成模拟对象。使用这些库,您还可以说“我不希望在代码期间调用投标”,因此它应该适合您

然而,你碰到了一些很难测试和量化的东西。是的,你可以证实预期的副作用确实发生了。除非你知道所有副作用,否则你如何确认没有其他副作用发生?例如,如果将来有人向接口添加一个新方法,该怎么办。如何确保所有单元测试,或其中任何单元测试,或无单元测试,验证对该额外方法的调用从未为现有测试调用过


这有关系吗?

+1与最初的设计是正确的想法有关。我很确定您不想使用
ioptionmpliedvol
IStrikeImpliedVol
接口;什么时候结束?你自己(Jonathan)已经用了一个非常恰当的术语来描述这条引导你走下的道路:一个混乱、复杂的网络。听雪熊的,谢谢。有时候我会对设计有点迂腐,当我认为可能会发生这种情况时,有一个像StackOverflow这样的社区可以与我交谈是件很棒的事情。