C# - Separate UI from business code - c#

I want to know what's the best practice for the following case :
I'm developing an application that need to be used on three different screen size : 240x320 ; 800x600 ; 1280x1024 (and only these three) in different languages (using localization).
So what I've done is to create a library by screen size, each implementing an interface defined in the project that calls these screens.
First question is, all my resources files are duplicated and that is many files to keep up to date (or with duplicate labels). Is there a simple way to change this?
Second question is, am I using the good approach or exists it a better way to do what I'm trying to do? By applying a design pattern maybe?
Sample code
The caller code :
public int X { get { return 800; } }
public int Y { get { return 600; } }
public interface IScreenForm
{
Form FormComponent { get; }
}
public interface IFormA : IScreenForm
{
TextBox UserTextBox { get; } // For use
}
public void LoadForm<T>()
where T:IScreenForm
{
if (!typeof(T).IsInterface)
{
throw new ArgumentException(typeof(T).Name + " is not an interface");
}
Assembly screenAssembly;
string screenResolutionDll = string.Format("{0}_{1}_screens.dll", this.X, this.Y);
screenAssembly = Assembly.LoadFrom(screenResolutionDll);
Type formType = screenAssembly.GetTypes()
.FirstOrDefault(t => t.GetInterfaces().Where(i => i.Name == typeof(T).Name).Count() > 0);
if (formType != null)
{
Form form = (Form)formType.GetConstructor(new Type[] { }).Invoke(null);
if (form != null)
{
form.Show();
}
else
{
throw new ArgumentException("Form doesn't provide a new() ctor");
}
}
else
{
throw new ArgumentException("Any form doesn't implement the interface : " + typeof(T).Name);
}
}
Screen DLL :
public partial class MyFirstForm : Form, caller.IFormA
{
public Form1()
{
InitializeComponent();
}
/* caller.IFormA interface implementation */
}

Arnaud, from my own experience, from reading, and from talking to experienced developers: When it comes to supporting multiple screen sizes and with localization, there are no magic bullets. For localization put all your strings in resource files, or even in data files.
As far as the screen sizes, I would not try to be too clever. Yes, make sure that none of your business / non-GUI logic gets duplicated, but duplicating resource files, forms, etc - I would not worry about it. Some GUI frameworks like Qt and GTK auto-resize and auto-position GUI-widgets (e.g. Qt has 'spacer' widgets). It works OK most of the time, however I still prefer explicit control. With GUI programming, there are often unexpected glitches, having three independent sets of GUI components will allow you to address them, should they arise. Some example sources of problems:
1) Font sizing.
2) Windows accessibility settings.
3) Some national languages have longer average words than others, the long words have trouble fitting in the real estate available.
If I were in your shoes, I would look for example how browsers handle this (e.g. mobile vs. desktop version) and I would try to find some practical advice on the Web (like here at SO). I doubt that books on design patterns will help much with this. Disclaimer: I am a design-pattern skeptic.

It is hard to advice without getting the whole picture but for some tips that might by handy read this
http://msdn.microsoft.com/en-us/library/ff648753.aspx
about the SmartClient software Factory.
It comes with architecural guidance and solutions for issue you often see in this kind of apps

Related

use PictureBox from another class c#

I hope my question will be clear
In Form1.cs i have PictureBox named: ico_ok
i would like to use this PictureBox in my new class that i bulit.
when i start typing ico... nothing appears.
what is the way to use this object in another class?
here the code:
public void button2_Click(object sender, EventArgs e)
{
lbl_check.Visible = true;
btn_continue.Visible = false;
txtbox_cusnumber.Enabled = false;
string userID = (txtbox_cusnumber.Text.ToString());
CheckOUinADexist checkou = new CheckOUinADexist(userID);
}
after that look at the new class:
namespace ChekingOUinActiveDirectory
{
class CheckOUinADexist
{
public CheckOUinADexist(string userID)
{
//this place i would like to use ico_ok
}
}
}
Thank you for helping.
Maayan
The simplest approach is probably to provide that class with the dependency on the PictureBox:
public CheckOUinADexist(string userID, PictureBox pbox)
{
pbox.[your code]
}
Then supply it when calling the method:
CheckOUinADexist checkou = new CheckOUinADexist(userID, ico_ok);
Whether or not this is the ideal approach depends on what you're going to be doing with that PictureBox inside that object, how portable that object needs to be across technology platforms, etc.
In general you don't want UI elements to permeate into non-UI logic. If CheckOUinADexist is a UI-bound class and exists solely to help the UI, then this isn't a problem. If it's part of business logic then you wouldn't want to couple that logic with the UI technology. Instead, you'd likely pass it the data needed from the PictureBox, but not the PictureBox itself.
This all depends a lot on the overall architecture of what you're trying to achieve here, which we don't know.
Basically you'd give the target class a reference to the "shared data" -- picture box in this case.
class CheckOUinADexist
{
PictureBox _picBox
public CheckOUinADexist(string userID, PictureBox picBox)
{
//this place i would like to use ico_ok
_picBox = picBox;
_picBox.myAction();
}
}
Whether you want to actually stored Picturebox as a field (as opposed to just use a parameter) depends on whether you need access to the field throughout the lifetime of the instance(s) or whether it is just needed for object construction. If you are not sure, you are safer (IMHO) just storing a reference in a field. Make further uses of it a lot easier.

Xamarin iOS memory leaks everywhere

We've been using Xamarin iOS for the last 8 months and developed a non-trivial enterprise app with many screens, features, nested controls. We've done our own MVVM arch, cross platform BLL & DAL as "recommended". We share code between Android and even our BLL/DAL is used on our web product.
All is good except now in release phase of project we discover irreparable memory leaks everywhere in the Xamarin iOS-based app. We've followed all the "guidelines" to resolve this but the reality is that C# GC and Obj-C ARC appear to be incompatible garbage collection mechanisms in the current way they overlay each other in monotouch platform.
The reality we've found is that hard cycles between native objects and managed objects WILL occur and FREQUENTLY for any non-trivial app. It's extremely easy for this to happen anywhere you use lambdas or gesture recognizers for example. Add in the complexity of MVVM and it's almost a guarantee. Miss just one of these situations and entire graphs of objects will never get collected. These graphs will lure other objects in and grow like a cancer, eventually resulting in a prompt and merciless extermination by iOS.
Xamarin's answer is an uninterested deferral of the issue and an unrealistic expectation that "devs should avoid these situations". Careful consideration of this reveals this as an admission that Garbage Collection is essentially broken in Xamarin.
The realization for me now is that you don't really get "garbage collection" in Xamarin iOS in the traditional c# .NET sense. You need employ "garbage maintanence" patterns actually get the GC moving and doing its job, and even then it'll never be perfect - NON DETERMINISTIC.
My company has invested a fortune trying to stop our app from crashing and/or running out of memory. We've basically had to explicitly and recursively dispose every damn thing in sight and implement garbage maintanence patterns into the app, just to stop the crashes and have a viable product we can sell. Our customers are supportive and tolerant, but we know this cannot hold forever. We are hoping Xamarin have a dedicated team working on this issue and get it nailed once and for all. Doesn't look like it, unfortunately.
Question is, is our experience the exception or the rule for non-trivial enterprise-class apps written in Xamarin?
UPDATE
See answer for DisposeEx method and solution.
I have shipped a non-trivial app written with Xamarin. Many others have as well.
"Garbage collection" isn't magic. If you create a reference that is attached to the root of your object graph and never detach it, it will not be collected. That's not only true of Xamarin, but of C# on .NET, Java, etc.
button.Click += (sender, e) => { ... } is an anti-pattern, because you don't have a reference to the lambda and you can never remove the event handler from the Click event. Similarly, you have to be careful that you understand what you're doing when you create references between managed and unmanaged objects.
As for "We've done our own MVVM arch", there are high profile MVVM libraries (MvvmCross, ReactiveUI, and MVVM Light Toolkit), all of which take reference/leak issues very seriously.
I used the below extension methods to solve these memory leak issues. Think of Ender's Game final battle scene, the DisposeEx method is like that laser and it disassociates all views and their connected objects and disposes them recursively and in a way that shouldn't crash your app.
Just call DisposeEx() on UIViewController's main view when you no longer need that view controller. If some nested UIView has special things to dispose, or you dont want it disposed, implement ISpecialDisposable.SpecialDispose which is called in place of IDisposable.Dispose.
NOTE: this assumes no UIImage instances are shared in your app. If they are, modify DisposeEx to intelligently dispose.
public static void DisposeEx(this UIView view) {
const bool enableLogging = false;
try {
if (view.IsDisposedOrNull())
return;
var viewDescription = string.Empty;
if (enableLogging) {
viewDescription = view.Description;
SystemLog.Debug("Destroying " + viewDescription);
}
var disposeView = true;
var disconnectFromSuperView = true;
var disposeSubviews = true;
var removeGestureRecognizers = false; // WARNING: enable at your own risk, may causes crashes
var removeConstraints = true;
var removeLayerAnimations = true;
var associatedViewsToDispose = new List<UIView>();
var otherDisposables = new List<IDisposable>();
if (view is UIActivityIndicatorView) {
var aiv = (UIActivityIndicatorView)view;
if (aiv.IsAnimating) {
aiv.StopAnimating();
}
} else if (view is UITableView) {
var tableView = (UITableView)view;
if (tableView.DataSource != null) {
otherDisposables.Add(tableView.DataSource);
}
if (tableView.BackgroundView != null) {
associatedViewsToDispose.Add(tableView.BackgroundView);
}
tableView.Source = null;
tableView.Delegate = null;
tableView.DataSource = null;
tableView.WeakDelegate = null;
tableView.WeakDataSource = null;
associatedViewsToDispose.AddRange(tableView.VisibleCells ?? new UITableViewCell[0]);
} else if (view is UITableViewCell) {
var tableViewCell = (UITableViewCell)view;
disposeView = false;
disconnectFromSuperView = false;
if (tableViewCell.ImageView != null) {
associatedViewsToDispose.Add(tableViewCell.ImageView);
}
} else if (view is UICollectionView) {
var collectionView = (UICollectionView)view;
disposeView = false;
if (collectionView.DataSource != null) {
otherDisposables.Add(collectionView.DataSource);
}
if (!collectionView.BackgroundView.IsDisposedOrNull()) {
associatedViewsToDispose.Add(collectionView.BackgroundView);
}
//associatedViewsToDispose.AddRange(collectionView.VisibleCells ?? new UICollectionViewCell[0]);
collectionView.Source = null;
collectionView.Delegate = null;
collectionView.DataSource = null;
collectionView.WeakDelegate = null;
collectionView.WeakDataSource = null;
} else if (view is UICollectionViewCell) {
var collectionViewCell = (UICollectionViewCell)view;
disposeView = false;
disconnectFromSuperView = false;
if (collectionViewCell.BackgroundView != null) {
associatedViewsToDispose.Add(collectionViewCell.BackgroundView);
}
} else if (view is UIWebView) {
var webView = (UIWebView)view;
if (webView.IsLoading)
webView.StopLoading();
webView.LoadHtmlString(string.Empty, null); // clear display
webView.Delegate = null;
webView.WeakDelegate = null;
} else if (view is UIImageView) {
var imageView = (UIImageView)view;
if (imageView.Image != null) {
otherDisposables.Add(imageView.Image);
imageView.Image = null;
}
} else if (view is UIScrollView) {
var scrollView = (UIScrollView)view;
// Comment out extension method
//scrollView.UnsetZoomableContentView();
}
var gestures = view.GestureRecognizers;
if (removeGestureRecognizers && gestures != null) {
foreach(var gr in gestures) {
view.RemoveGestureRecognizer(gr);
gr.Dispose();
}
}
if (removeLayerAnimations && view.Layer != null) {
view.Layer.RemoveAllAnimations();
}
if (disconnectFromSuperView && view.Superview != null) {
view.RemoveFromSuperview();
}
var constraints = view.Constraints;
if (constraints != null && constraints.Any() && constraints.All(c => c.Handle != IntPtr.Zero)) {
view.RemoveConstraints(constraints);
foreach(var constraint in constraints) {
constraint.Dispose();
}
}
foreach(var otherDisposable in otherDisposables) {
otherDisposable.Dispose();
}
foreach(var otherView in associatedViewsToDispose) {
otherView.DisposeEx();
}
var subViews = view.Subviews;
if (disposeSubviews && subViews != null) {
subViews.ForEach(DisposeEx);
}
if (view is ISpecialDisposable) {
((ISpecialDisposable)view).SpecialDispose();
} else if (disposeView) {
if (view.Handle != IntPtr.Zero)
view.Dispose();
}
if (enableLogging) {
SystemLog.Debug("Destroyed {0}", viewDescription);
}
} catch (Exception error) {
SystemLog.Exception(error);
}
}
public static void RemoveAndDisposeChildSubViews(this UIView view) {
if (view == null)
return;
if (view.Handle == IntPtr.Zero)
return;
if (view.Subviews == null)
return;
view.Subviews.ForEach(RemoveFromSuperviewAndDispose);
}
public static void RemoveFromSuperviewAndDispose(this UIView view) {
view.RemoveFromSuperview();
view.DisposeEx();
}
public static bool IsDisposedOrNull(this UIView view) {
if (view == null)
return true;
if (view.Handle == IntPtr.Zero)
return true;;
return false;
}
public interface ISpecialDisposable {
void SpecialDispose();
}
Couldn't be agree more with the OP that "Garbage Collection is essentially broken in Xamarin".
Here's an example shows why you have to always use a DisposeEx() method as suggested.
The following code leaks memory:
Create a class the inherits UITableViewController
public class Test3Controller : UITableViewController
{
public Test3Controller () : base (UITableViewStyle.Grouped)
{
}
}
Call the following code from somewhere
var controller = new Test3Controller ();
controller.Dispose ();
controller = null;
GC.Collect (GC.MaxGeneration, GCCollectionMode.Forced);
Using Instruments you will see that there are ~ 274 persistent objects with 252 KB never collected.
Only way to fix this is add DisposeEx or similar functionality to the Dispose() function and call Dispose manually to ensure disposing == true.
Summary: Creating a UITableViewController derived class and then disposing/nulling will always cause the heap to grow.
iOS and Xamarin have a slightly troubled relationship. iOS uses reference counts to manage and dispose of its memory. The reference count of an object gets incremented and decremented when references are added and removed. When the reference count goes to 0, the object is deleted and the memory freed. Automatic Reference Counting in Objective C and Swift help with this, but it’s still difficult to get 100% right and dangling pointers and memory leaks can be a pain when developing using native iOS languages.
When coding in Xamarin for iOS, we have to bear reference counts in mind as we will be working with iOS native memory objects. In order to communicate with the iOS operating system, Xamarin creates what are known as Peers which manage the reference counts for us. There are two types of Peers – Framework Peers and User Peers. Framework Peers are managed wrappers around well-known iOS objects. Framework Peers are stateless and therefore hold no strong references to the underlying iOS objects and can be cleaned up by the garbage collectors when required – and don’t cause memory leaks.
User Peers are custom managed objects that are derived from Framework Peers. User Peers contain state and are therefore kept alive by the Xamarin framework even if your code has no references to them – e.g.
public class MyViewController : UIViewController
{
public string Id { get; set; }
}
We can create a new MyViewController, add it to the view tree, then cast a UIViewController to a MyViewController. There may be no references to this MyViewController, so Xamarin needs to ‘root’ this object to keep this it alive whilst the underlying UIViewController is alive, otherwise we will lose the state information.
The problem is that if we have two User Peers that reference each other then this creates a reference cycle that cannot be automatically broken – and this situation happens often!
Consider this case:-
public class MyViewController : UIViewController
{
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear (animated);
MyButton.TouchUpInside =+ DoSomething;
}
void DoSomething (object sender, EventArgs e) { ... }
}
Xamarin creates two User Peers that reference each other – one for MyViewController and another for MyButton (because we have an event handler). So, this will create a reference cycle that will not be cleared up by the garbage collector. In order to have this cleared up, we must unsubscribe the event handler, and this is usually done in the ViewDidDisappear handler – e.g.
public override void ViewDidDisappear(bool animated)
{
ProcessButton.TouchUpInside -= DoSomething;
base.ViewDidDisappear (animated);
}
Always unsubscribe to your iOS event handlers.
How to diagnose these memory leaks
A good way to diagnose these memory problems is to add some code in debug to the Finalisers of the classes derived from iOS wrapper classes – such as UIViewControllers. (Although only put this in your debug builds and not in release builds because it’s reasonably slow.
public partial class MyViewController : UIViewController
{
#if DEBUG
static int _counter;
#endif
protected MyViewController (IntPtr handle) : base (handle)
{
#if DEBUG
Interlocked.Increment (ref _counter);
Debug.WriteLine ("MyViewController Instances {0}.", _counter);
#endif
}
#if DEBUG
~MyViewController()
{
Debug.WriteLine ("ViewController deleted, {0} instances left.",
Interlocked.Decrement(ref _counter));
}
#endif
}
So, Xamarin’s memory management is not broken in iOS, but you do have to be aware of these ‘gotchas’ which are specific to running on iOS.
There is an excellent page by Thomas Bandt called Xamarin.iOS Memory Pitfalls that goes into this in more detail and also provides some very useful hints and tips.
I noticed in your DisposeEx method you dispose of the collection view source and table view source before you kill the visible cells of that collection. I noticed when debugging that the visible cells property gets set to an empty array therefore, when you start to dispose visible cells, they no longer "exist" hence it becomes an array of zero elements.
Another thing I noticed is that you will run into inconsistency exceptions if you don't remove the parameter view from its super view, I've noticed especially with setting the layout of the collection view.
Other than that I've had to implement something similar on our side.

Real Time Data Binding

All -
I have currently have a POC WPF project which works end to end. The application simulates real-time market data being published through a library (Publisher) and my WPF client is Subscriber (has the handler method). It uses Custom Events to publish data.
Question I have is this:
1) I want to implement Producer Consumer - so my handler doesn't pull the data into Observable Collection directly.
2) I precisely know how to implement Producer/Consumer C# snippets (http://msdn.microsoft.com/en-us/library/hh228601.aspx) but wanted to more understand how this will fit in my current architecture. Here is a diagram
3) Can anybody help me out with code approach, links etc.
MainWindowViewModel.cs
public class MainWindow_VM : ViewModelBase
{
#region Properties
public myCommand SbmtCmd { get; set; }
public ObservableCollection<StockModel> stocks { get; set; }
#endregion
#region Fields
private readonly Dispatcher currentDispatcher;
#endregion
public MainWindow_VM()
{
SbmtCmd = new myCommand(mySbmtCmdExecute, myCanSbmtCmdExecute);
currentDispatcher = Dispatcher.CurrentDispatcher;
stocks = new ObservableCollection<StockModel>();
}
private void mySbmtCmdExecute(object parameter)
{
MarketDataProvider p = new MarketDataProvider();
p.OnMarketData += new EventHandler<MarketDataEventArgs>(handlermethod);
p.GenerateMarketData();
}
private bool myCanSbmtCmdExecute(object parameter)
{
return true;
}
// Subscriber method which will be called when the publisher raises an event
private void handlermethod(object sender, MarketDataEventArgs e)
{
foreach (Stock s in e.updatedstk)
{
StockModel sm = new StockModel();
sm.symbol = s.symbol;
sm.bidprice = s.bidprice;
sm.askprice = s.askprice;
sm.lastprice = s.lastprice;
currentDispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate()
{
if (sm != null)
{
if (stocks.Any(x => x.symbol == sm.symbol))
{
var found = stocks.FirstOrDefault(x => x.symbol == sm.symbol);
int i = stocks.IndexOf(found);
stocks[i] = sm;
}
else
{
stocks.Add(sm);
}
}
});
}
}
}
I have done some projects with market feeds and your chart looks fine conceptually. To avoid scalability issues, or to design proactively against scalability issues, you can consider making your producer/consumer box have multiple instances to accommodate multiple feeds and/or multiple instruments within the feed. If, for example, a given market becomes densely volatile, you don't want all the other instruments starved for data.
Also, some people like to switch feeds for a given instrument based upon arbitrary criteria, like getting YEN from London until the gold fix, and then switching to NYC, and then again switching to Tokyo.
The other thing I can mention is for the arrow going out of the producer/consumer box to pass POCO DTO's only. It adds to the value of your application and also makes isolation testing a lot easier.
Testing off live feeds (or even simulated feeds) is scant because they don't capture all the conditions that need to be tested before an app is deployable.
Finally I would mention that the producer/consumer pattern was implemented starting in .NET 4.0 with the System.Collections.Concurrent name space... http://msdn.microsoft.com/en-us/library/dd287147.aspx I have been using these classes in production and they really cut through the need to test a home-grown design pattern.
I've created a UI toolkit called ReactiveTables which allows you to create live tables which can be joined, filtered, extended with calculated columns and then bound to WPF controls. The tables expose an IObservable interface and have been designed for performance.
You can hook the tables up directly to your producer/consumer implementation and then bind them to your views. The tables will notify on changes to individual cells and there is a helper class for translating this into INotifyPropertyChanged events.
On the receiving side there are classes which can throttle updates to the UI tables and marshal form your data threads to the UI thread.

Passing objects between classes in Windows Phone/C#

I'm new to Windows Phone and C#, enjoying the change from Objective-C and Java.
I cant find the way to pass an object from one class to another. I came across some sample code looking on MSDN but I tink that maybe its not applicable for what I need.
private void meetingList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (meetingList.SelectedIndex != -1)
{
Meeting aMeeting = (Meeting)meetingList.SelectedItem;
this.NavigationService.Navigate(new Uri("/MeetDetails.xaml", UriKind.Relative));
ApplicationBar.IsVisible = true;
}
}
How can I pass my Meeting Object 'aMeeting' into my MeetDetails class so that I can display all the details to the user.
I know I can break it down, and pass in all the vars from the 'aMeeting' by using something like this:
this.NavigationService.Navigate(new Uri("/MeetDetails.xaml?Meeting=" +
aMeeting.meetName + "&TheDate=" +
aMeeting.meetDate, UriKind.Relative));
Is there something I've missed? Are there alternative ways you guys would recommend?
Many Thanks,
-Code
What you've posted is a good way of transferring simple data about the place. However it becomes a pain when you have to pass a complex object between pages.
The recommended way is to use the MVVM pattern (from wikipedia and MSDN). This gives you a way to separate the View from everything else by making use of data binding. The best tutorials I have seen is to watch the videos on MSDN.
var t1 = App.Current as App;
t1.SSIDToken = stData1SSID;
t1.CSRFToken = stData1CSRF;
this works real good, just make the members u need in the app.cs file
(here it was :
public string SSIDToken {get; set;}
public string CSRFToken {get; set;}
Then create the top code to create a var to serve as temp buffer.
If you want to get back the values use the same code :
var t1 = App.Current as App;
thisisatextbox.Text = t1.SSIDToken;
thisisalsoatextbox.Text = t1.CSRFToken;
Further info ;
http://www.eugenedotnet.com/2011/07/passing-values-between-windows-phone-7-pages-current-context-of-application/
EDIT: After a couple of months of experience, noticed you can add
public static new App Current
{
get { return Application.Current as App; }
}
In the App.xaml (In the public class App) to be able to call upon App.Current without having to declare it every single time!
Now you can use App.Current.CSRFToken = "" || string CSRFTk = App.Current.CSRFToken;
You might want to consider a manager class with properties which could store your current Meeting object. This would then be set in your SelectionChanged event handler and then accessed in your MeetDetails page. The manager class is defined externally to your pages so that it can be accessed from all your pages.

How to implement a Stack class in C#, with pre/postconditions and invariants?

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)];
}
}
}
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:
Precondition is what must be true prior to a method being executed -- what clients promise your method.
Invariant is what must remain publicly true at all times as far as clients of your class are concerned.
Postcondition is what must be true following a method execution -- what your method promises to clients.
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:
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(elements != null);
}
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:
Contract.Requires(size > 0);
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):
Contract.Ensures(Contract.OldValue<int>(size) > size);
Good luck with it -- contracts are cool and useful. It's a very clean way to code.
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

Categories