116 lines
No EOL
3.5 KiB
Text
116 lines
No EOL
3.5 KiB
Text
[](https://classroom.github.com/a/4Iki-2WU)
|
|
:sectnums:
|
|
:nofooter:
|
|
:toc: left
|
|
:icons: font
|
|
:data-uri:
|
|
:source-highlighter: highlightjs
|
|
:stem:
|
|
|
|
= Int.01 -- Digits Sequence
|
|
|
|
A simple, first assignment for implementing interfaces.
|
|
We did something very similar together in the workshop, so this exercise should be easy to solve for you.
|
|
|
|
Your task is to implement a class which takes a number and:
|
|
|
|
. Allows iteration over its digits => `IEnumerable`
|
|
. Can compare two digits => `IComparable`
|
|
|
|
[plantuml]
|
|
----
|
|
@startuml
|
|
hide empty fields
|
|
hide empty methods
|
|
|
|
class Digits <<sealed>> {
|
|
-int _number [readonly]
|
|
|
|
+Digits(int)
|
|
+int CompareTo(Digits?)
|
|
+IEnumerator<int> GetEnumerator()
|
|
+IEnumerator IEnumerable.GetEnumerator()
|
|
+string ToString() [override]
|
|
}
|
|
|
|
class DigitEnumerator <<sealed>> {
|
|
-int _number [readonly]
|
|
+int Current [readonly]
|
|
+object IEnumerator.Current [readonly]
|
|
|
|
+DigitEnumerator(int)
|
|
+bool MoveNext()
|
|
+void Reset()
|
|
+Dispose()
|
|
}
|
|
|
|
interface IEnumerable<int> {
|
|
{abstract} +IEnumerator<int> GetEnumerator()
|
|
{abstract} +IEnumerator IEnumerable.GetEnumerator()
|
|
}
|
|
interface IComparable<Digits> {
|
|
{abstract} +int CompareTo(Digits?)
|
|
}
|
|
interface IEnumeratorNG {
|
|
{abstract} +object Current [readonly]
|
|
|
|
{abstract} +bool MoveNext()
|
|
{abstract} +void Reset()
|
|
}
|
|
note bottom: Actual name is just 'IEnumerator'\n using NG postfix due to PlantUML issue
|
|
interface IEnumerator<int> {
|
|
{abstract} +int Current [readonly]
|
|
}
|
|
interface IDisposable {
|
|
{abstract} +Dispose()
|
|
}
|
|
|
|
IEnumerable <|-- Digits
|
|
IComparable <|-- Digits
|
|
IEnumerator <|-- DigitEnumerator
|
|
IEnumeratorNG <|-- IEnumerator
|
|
IDisposable <|-- IEnumerator
|
|
|
|
@enduml
|
|
----
|
|
|
|
== Implementation Requirements
|
|
=== `DigitEnumerator`
|
|
|
|
* Implements `IEnumerator<int>`
|
|
* Negative numbers are simply converted to positive ones
|
|
** e.g. -899 => 899
|
|
* _Can_ be reset
|
|
* `IEnumerator.Current` should be trivial
|
|
* `Dispose`
|
|
** Part of the `IDisposable` interface we received transitively
|
|
** Used to release resources -- will become very important in the future!
|
|
** https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-9.0[Read through the documentation]
|
|
** You should now have realized what you have to implement here in this case 😉
|
|
* *Important:*
|
|
** Relying on the compiler to generate a state machine will not always be possible (in complex scenarios)
|
|
** Also, you have to proof that you can do it yourself
|
|
** => Implement the enumerator _without_ using `yield`!
|
|
* Implement it _without_ using a string!
|
|
* Example: Number 91302 => 9, 1, 3, 0, 2
|
|
|
|
TIP: Some additional, private fields, properties or maybe even methods might be useful
|
|
|
|
=== `Digits`
|
|
|
|
* Implements `IEnumerable<int>` & `IComparable<Digits>`
|
|
* Negative numbers are simply converted to positive ones
|
|
** Same as for the enumerator
|
|
* `CompareTo`
|
|
** Create a _clean_ implementation which checks for same and null references _before_ doing the actual comparison
|
|
* `GetEnumerator` has to make use of `DigitEnumerator`
|
|
* `IEnumerable.GetEnumerator` should be trivial
|
|
* `ToString`
|
|
** Just for good practice make sure the string output if formatted for the _invariant_ culture
|
|
|
|
== Tasks
|
|
|
|
. Complete the implementation according to the specified requirements
|
|
. Create the XMLDoc for the application -- _think_ which comments are required and which might already be present
|
|
|
|
NOTE: Unit tests have been provided with the starter code |