您认为“自动接口实现”在 .NET / C# 中有用吗?
-
19-08-2019 - |
题
考虑一下:
public class interface Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
和这个:
public class StubPerson : IPerson
{
int ID { get { return 0; protected set { } }
string FirstName { get { return "Test" } set { } }
string LastName { get { return "User" } set { } }
string FullName { get { return FirstName + " " + LastName; } }
}
用法:
IPerson iperson = new Person();
或者:
IPerson ipersonStub = new StubPerson();
或者:
IPerson ipersonMock = mocks.CreateMock<IPerson>();
所以实际上我们正在声明 IP人 接口和 人 同时上课:
public class interface Person : IPerson
您认为在 .NET/C# 中提供这种支持有用吗?
编辑:
由于大量混乱,我认为我需要澄清拟议的目的:
如果没有这个功能,你将不得不编写:
interface IPerson
{
int ID { get; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get; }
}
还有这个:
public class Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
我根本不建议任何语义改变。
解决方案
我认为的同样的事情在不久前,特别是在使用的情况下,你只能有一个生产实现接口的,但你要嘲笑它进行测试。目前,它最终被往昔有点像.C / h文件。
我怀疑在它的好处是通过额外的复杂性无论是在语言,然后再把阅读代码压倒结束。我仍然有兴趣看到它探索更彻底虽然。即使这样,还有其他的东西我的优先级列表上一路走高 - 对于不变性在顶部更好的支持:)
其他提示
让我看看,如果我知道你要问的:
我们为什么不能声明一个接口:
interface IPerson
{
string Name {get;set;}
int ID {get;set;}
}
和其实现该接口将继承它的属性,而不必类重新声明它们:
class Person : IPerson { }
//person now has properties Name and ID
你不能做到这一点,即使你的界面代码和类代码的文本是非常相似的原因,他们的的意思是非常的不同的东西。接口只是说“实现者将有getter和setter字符串名称”。这是说,类“返回私有字段调用的名称吸气时。”即使您使用自动属性的快捷方式,让编译器实现这个逻辑,它仍然是逻辑的,属于在类。只是因为:
string Name {get;set;}
看起来中的接口和在一类是相同的,但这并不意味着甚至远程同样的事情。
这将是非常危险的编译器来实现任意逻辑,以满足您的合同给你,而不是在你还没有实现他们的编译时间抱怨。它可以引入错误非常难以追查。有编译器回落到默认行为没有行为定义时是一个非常,非常糟糕的主意。
我相信艾菲尔做这样的事情在.NET上,以支持多重继承。类声明自动地产生对应的接口。当类的类型被称为,编译器大多发射到所述接口的引用类型代替。主要的例外是在过程的构造表达式。
不过,我想其他的答案将帮助您了解在不同的具体类使用的接口抽象逻辑,我还以为你能完成类似的东西,你要使用内置于VS的重构工具是什么。
定义类...
public class Person
{
public int ID { get; protected set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
然后点击右键,选择Refactor - >提取接口
这将创建包含的类的定义中的接口的单独文件,则可以再模制接口,并相应地实现类。
提取接口:
interface IPerson
{
string FirstName { get; set; }
string FullName { get; }
int ID { get; }
string LastName { get; set; }
}
我想我错过了点 - 你在通过混合类和接口一起完成?你用这种方法解决什么问题?
此:
IPerson iperson = new Person();
已经在C#合法的。
修改:用于澄清 - 上面的代码是合法给出以下内容:
interface IPerson { }
class Person : IPerson { }
我想至少像Visual Studio从一个界面自动属性实现我的财产,如果我要求它这样做。
不幸的是,此选项不,我必须处理未实现异常存根
没有,因为你将被迫公开接口的所有公共成员。尝试 ReSharper的,永不再担心这个。
Resharper可以提供这种功能,例如,
- 你可以写你的人类的第一个。
- 你可以提取你的接口由 拉员了 到IPerson接口。
因此你可以有些工作室自动生成的执行情况的存根。
更新
无论如何,让我们阐述在第一接口,理由是代码你提供你的问题:
public class interface Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
你必须明白,一个接口不是一个抽象的类。一个接口的仅仅是 一个合同, 蓝图中的各种各样,这意味着它会告诉对象的期望是什么在另一个目的没有真正关心它是如何实现的。
一个抽象的类,另一方面,可以包含段的功能,可以继承和复盖。
在上述情况下,您的"接口"是无效的,因为:
- 你不能宣布范围限制在接口(公共的、私人的、保护、内部),因为这是一个执行情况的细节
- 你不能声明默认的执行情况(例如,您
FullName
酒店)因为同样的原因,这是一个执行情况的细节
在我看来,似乎什么样的你真的真的想要的是一个抽象的类,例如,
public abstract class BasePerson
{
public abstract int ID { get; protected set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual string FullName { get { return FirstName + " " + LastName; } }
}
我只是猜想,但也许这就是你真正需要的。
更新2
好吧,我认为我在什么你希望发生的,所以你想要的是能够编写这样的:
public interface IPerson
{
int ID { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get; }
}
然后你的实现只需要写这样的:
public class Person : IPerson
{
public int ID { get; protected set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
无需指定的名字和姓氏的性质。
第一个问题,我们需要解决的是连接不允许访问符其实施:会发生什么,是的性质将要继承的默认接符,这是私有的。
第二是事实,而在我们的眼睛 string FirstName { get; set; }
在一个接口 public string FirstName { get; set; }
在一个类别相同,他们实际上不是:
- 在一个接口,将财产的定义将表明签名方法对于吸气和/或设置方法将适用于所有类别实施,接口。
- 在一类中,财产的定义将指示CLR创建一个匿名的目的哪些将保留价值的,所述财产。
细微的差别程序员,世界上除了为编译器。
最后,当你指定要实现一个接口,Visual Studio并执行synctactic魔法自动使这些财产的存根。
我认为更好的抽象是一种特质,或者,正如我所描述的 这里, , 一名角色。这就像一个带有代码的界面。您的示例可以这样编码:
public role RPerson {
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
public class Person : RPerson { }
public class StubPerson : RPerson {
int ID { get { return 0; protected set { } }
string FirstName { get { return "Test" } set { } }
string LastName { get { return "User" } set { } }
string FullName { get { return FirstName + " " + LastName; } }
}
// ...
RPerson rperson = new Person();
RPerson rpersonStub = new StubPerson();