如何在 C# 中实现具有前置/后置条件和不变量的 Stack 类?
有没有人有关于如何/什么是在 C# 中实现 Stack 类的最佳方法的示例或想法?我知道已经有一个 Stack 类,但我需要了解如何实际实现 Stack 类。
我还需要有关如何在 C# 中使用 Contract 来指定此类的前置条件、后置条件和不变量的建议。我想我以前在 ASP.NET MVC 架构中创建模型时使用过类似的东西,但我不完全确定它是否是相同的东西并且以相同的方式工作。 (我对先决条件/后置条件/不变量有点迷失,如果您还不能告诉我 - 所以请耐心等待。)
我的主要问题 - 有人可以给我关于的建议吗为诸如堆栈之类的类正确使用契约。
是的,我已经付出了努力:
public interface IStack
{
void Push(Object e);
Object Pop();
Object Top();
void EnsureCapacity();
}
}
public class Stack : IStack
{
private Object[] elements;
private int size = 0;
public Stack()
{
elements = new Object[0];
}
public void Push(Object e)
{
// check if this array capacity has been reached and increase if needed
EnsureCapacity();
elements[size++] = e;
}
public Object Pop()
{
// check if the method call is invalid for the object's current state
if (size == 0) throw new InvalidOperationException("Stack.Pop");
Object result = elements[--size];
elements[size] = null;
return result;
}
public Object Top()
{
// check if the method call is invalid for the object's current state
if (size == 0) throw new InvalidOperationException("Stack.top");
return elements[(size - 1)];
}
private void EnsureCapacity()
{
if (elements.Length == size)
{
Object[] oldElements = elements;
elements = new Object[(2 * size + 1)];
}
}
}
Does anyone have any examples or ideas on how / what is the best way to implement a Stack class in C#? I understand that there is already a Stack class, but I need to understand how to actually implement a Stack class.
I also need advice on how to use Contracts in C# to specify preconditions, postconditions, and invariants for this class. I think I have used something similar before when creating models in the ASP.NET MVC architecture, but I'm not entirely sure if it is the same thing and works the same way. (I'm a bit lost on the preconditions/postconditions/invariants, if you couldn't already tell - so please bear with me.)
My main question - could someone give me advice on properly using Contracts for a class such as a Stack.
Yes, I have laid out effort:
public interface IStack
{
void Push(Object e);
Object Pop();
Object Top();
void EnsureCapacity();
}
}
public class Stack : IStack
{
private Object[] elements;
private int size = 0;
public Stack()
{
elements = new Object[0];
}
public void Push(Object e)
{
// check if this array capacity has been reached and increase if needed
EnsureCapacity();
elements[size++] = e;
}
public Object Pop()
{
// check if the method call is invalid for the object's current state
if (size == 0) throw new InvalidOperationException("Stack.Pop");
Object result = elements[--size];
elements[size] = null;
return result;
}
public Object Top()
{
// check if the method call is invalid for the object's current state
if (size == 0) throw new InvalidOperationException("Stack.top");
return elements[(size - 1)];
}
private void EnsureCapacity()
{
if (elements.Length == size)
{
Object[] oldElements = elements;
elements = new Object[(2 * size + 1)];
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您愿意,为了开始使用 Microsoft 代码合同,我曾发表过一篇关于它的博客文章 。这篇文章涵盖了前置条件、后置条件和不变量的基本知识。
作为这些概念的总结,您可以将它们视为如下:
所以,在我的脑海中,对于堆栈来说,一个容易想到的事情可能是一个不变量。如果您使用数组对堆栈进行建模,则可以在该类上声明一个不变量,即该数组永远不会设置为 null,例如,您可以定义该不变量方法:
看起来您已经有了一个前提条件pop 方法 - 您想说用户有责任确保执行 pop 时堆栈不为空。因此,在 pop 方法的开头,您需要:
最后,您可以在 pop 上指定一个后置条件,该大小将始终小于 pop 操作之前的大小(如果您愿意,您可以得到更具体的信息) ):
祝你好运——合同很酷而且很有用。这是一种非常干净的编码方式。
If you want, for getting started using Microsoft Code Contracts, I made a blog post about it once. That post covers the very basic of preconditions, post-conditions, and invariants.
As a summary of the concepts, you can think of them as follows:
So, off the top of my head, for a stack, an easy thing to think of might be an invariant. If you're modeling the stack with an array, you might declare an invariant on the class that the array is never set to null, for example you'd define the invariant method:
It looks like you've already got a precondition on your pop method - you want to say that it's incumbent on the user to make sure that the stack is not empty when he executes a pop. So, at the beginning of the pop method, you'd have:
And finally, you might specifiy a post-condition on pop, that size will always be less than it was before the pop operation (you could get more specific if you like):
Good luck with it -- contracts are cool and useful. It's a very clean way to code.
C# 中实现的许多集合都是基于数组的。您可以使用数组并将元素添加到末尾,保留顶部 elemnet 的索引并在推送新元素时增加它,当然,当新对象出现并且存在时,数组将“必须动态扩展”(被新元素替换)当前数组中没有它们的位置。
代码合同在 http://research.microsoft.com 上提供了非常好的文档/en-us/projects/contracts/userdoc.pdf
Many of collections implemented in c# are based on arrays. You could use array and add elements to the end, keep index of a top elemnet and increase it while new elements are pushed, of course array will "have to be extended" ( replaced by new one ) dynamically when new objects appear and there is no place for them in current array.
code contracts have pretty good documentation available at http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf