C# 当我键入对象时,我使用接口或类有什么区别吗?
我创建了这个界面:C# 当我键入对象时,我使用接口或类有什么区别吗?,c#,C#,我创建了这个界面: public interface IPhrase { int CategoryId { get; set; } string PhraseId { get; set; } string English { get; set; } string Romaji { get; set; } string Kana { get; set; } string Kanji { get; set; } } var phrases = db2
public interface IPhrase
{
int CategoryId { get; set; }
string PhraseId { get; set; }
string English { get; set; }
string Romaji { get; set; }
string Kana { get; set; }
string Kanji { get; set; }
}
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
var eng = phrases[0].English; //**THIS WONT WORK**
这门课:
public class Phrase : IPhrase
{
public Phrase()
{
}
public int CategoryId { get; set; }
public string PhraseId { get; set; }
public string English { get; set; }
public string Romaji { get; set; }
public string Kana { get; set; }
public string Kanji { get; set; }
}
在这里,此代码返回数据并将其类型转换为短语:
var phrases = db2.Query<Phrase>("SELECT * FROM Phrase", ans);
var phrases = db2.Query<IPhrase>("SELECT * FROM Phrase", ans);
var-phrases=db2.Query(“从短语中选择*”,ans);
var phrases=db2.Query(“从短语中选择*”,ans);
我想知道的是,在这里使用
IPhrase
或短语是否有任何区别/优势?在本例中创建IPhrase
接口有哪些优点(如果有的话)。这会导致更可读的代码吗?接口是一种契约,它保证实现接口的任何类都将实现接口中定义的方法和属性。这允许您使用接口创建方法、列表等,这些方法、列表等接受实现接口的任何类,例如
public interface IExample
{
int GetInt();
}
public void ProcessInt(IExample value)
{
var tempInt = value.GetInt();
// Do processing here
}
这允许将实现接口IExample的任何具体类传递给此方法。方法被保证任何传递的具体类都将实现方法GetInt。接口是一个契约,它保证实现接口的任何类都将实现接口中定义的方法和属性。这允许您使用接口创建方法、列表等,这些方法、列表等接受实现接口的任何类,例如
public interface IExample
{
int GetInt();
}
public void ProcessInt(IExample value)
{
var tempInt = value.GetInt();
// Do processing here
}
这允许将实现接口IExample的任何具体类传递给此方法。该方法保证任何传递的具体类都将实现方法GetInt。在本地使用接口和具体对象之间没有区别,如您的示例所示。主要区别在于,当您将接口与具体类作为API中的参数或构造函数参数发送时,最好使用接口,以便实现解耦和可测试性
对于你的问题,简短的回答是不,没有区别,你是想使用接口还是具体的对象作为局部变量是你自己的选择(对你来说更容易理解)。不要忘记,字段和属性最好声明为接口,这样可以提供更大的灵活性
在使用具体对象而不是局部接口时,应该考虑的最后一件事是,您可能希望有一天更改为您提供该对象的方法的签名,以返回实现相同接口的另一种对象,在这种情况下,您也应该更改局部变量(即使情况不是很糟,而且很少发生,我也必须注意到),如以下示例所示:
interface IAnimal
{
void Run();
}
class Cat : IAnimal
{
public void Run()
{
//...
}
}
class Dog : IAnimal
{
public void Run()
{
//...
}
}
如果您的代码中有一个方法返回您使用的Cat
:
Cat GetAnimal()
{
return new Cat();
}
Cat myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
然后,如果将GetAnimal
签名更改为返回Dog
,则应更改代码以编译为:
Dog myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
但是,如果您使用的是接口,则当方法的签名发生更改时,代码需要更改的可能性较小:
IAnimal myAnimal = GetAnimal(); //this is working whether a Cat or a Dog is received.
myAnimal.Run();
但是这种情况也很少发生。为愚蠢的猫狗示例感到抱歉!在本地使用接口和具体对象之间没有区别,就像在您的示例中一样。主要区别是当您将接口与具体类作为API中的参数或构造函数参数发送时,最好在接口,以便实现解耦和可测试性
对于您的问题,简短的回答是“不”,没有区别,您是想使用接口还是具体对象作为局部变量是您自己的选择(您觉得更可读)。不要忘记,字段和属性最好声明为接口,这样可以提供更大的灵活性
在使用具体对象而不是局部接口时,应该考虑的最后一件事是,您可能希望有一天更改为您提供该对象的方法的签名,以返回实现相同接口的另一种对象,在这种情况下,您也应该更改局部变量(即使情况不是很糟,而且很少发生,我也必须注意到),如以下示例所示:
interface IAnimal
{
void Run();
}
class Cat : IAnimal
{
public void Run()
{
//...
}
}
class Dog : IAnimal
{
public void Run()
{
//...
}
}
如果您的代码中有一个方法返回您使用的Cat
:
Cat GetAnimal()
{
return new Cat();
}
Cat myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
然后,如果将GetAnimal
签名更改为返回Dog
,则应更改代码以编译为:
Dog myAnimal = GetAnimal(); //note that here it is expected a Cat
myAnimal.Run();
但是,如果您使用的是接口,则当方法的签名发生更改时,代码需要更改的可能性较小:
IAnimal myAnimal = GetAnimal(); //this is working whether a Cat or a Dog is received.
myAnimal.Run();
但是这种情况也很少发生。对于愚蠢的猫和狗的例子,我很抱歉!对于可以继承的对象:
其他物体
接口
对象
如果您有一个动物
对象,那么狗
对象可以继承它,因为它是一个动物
对于对象继承,请考虑以下短语:我是一个……\u您的对象\u……
接口
有了一个接口,你可以把它看作是该对象的一个描述符。例如IWalkOnTwoLegs
或ICanSwim
所以想想这个短语:我能行....\u你的界面..
现在回答您的问题,使用或不使用界面会有什么不同吗?
当然,在这种情况下不是这样,但是如果您扩展短语并创建一个问题
对象和一个语句
对象,并且它们继承自短语
,您可以选择返回所有短语(问题和语句)或仅为问题的短语
或仅为语句
您还可以对短语应用一个界面,上面写着iaminformench
和IAmInSpanish
,这样您就可以扩展SpanishPhrase
和FrenchPhrase
对象。
现在您可以返回所有短语,无论它们是否为qu