Explicit implementation of interface's GetEnumerator causes stack overflow - c#

I'm doing my best to code against interfaces whenever possible, but I'm having some issues when it comes to collections. For example, here are a couple interfaces I'd like to use.
public interface IThing {}
public interface IThings : IEnumerable<IThing> {}
Here are the implementations. In order to implement IEnumerable<IThing> I need to explicitly implement IEnumerable<IThing>.GetEnumerator() in Things.
public class Thing : IThing {}
public class Things : List<Thing>, IThings
{
IEnumerator<IThing> IEnumerable<IThing>.GetEnumerator()
{
// This calls itself over and over
return this.Cast<IThing>().GetEnumerator();
}
}
The problem is that the GetEnumerator implementation causes a stack overflow. It calls itself over and over again. I can't figure out why it'd decide to call that implementation of GetEnumerator instead of the implementation provided by the result of this.Cast<IThing>(). Any ideas what I'm doing wrong? I'm willing to bet it's something extremely silly...
Here's some simple test code for the above classes:
static void Enumerate(IThings things)
{
foreach (IThing thing in things)
{
Console.WriteLine("You'll never get here.");
}
}
static void Main()
{
Things things = new Things();
things.Add(new Thing());
Enumerate(things);
}

Use this instead:
public class Things : List<Thing>, IThings
{
IEnumerator<IThing> IEnumerable<IThing>.GetEnumerator()
{
foreach (Thing t in this)
{
yield return t;
}
}
}
Or you could work with containment instead.

IEnumerator<IThing> IEnumerable<IThing>.GetEnumerator()
{
// This calls itself over and over
return this.Cast<IThing>().GetEnumerator();
}
It's a recursive call with no break condition, you're going to get a stack overflow, because it's going to very quickly fill up the stack.
You're casting to an interface, which does not do what you think it does. In the end you are just calling this.GetEnumerator(); which is the function you're already in, thus recursing. Perhaps you mean base.GetEnumerator();

Generally, you would probably want to decouple the implementation of the Things collection from the implementation of the Thing object. The Things class is capable of working with any implementation of IThing, not just the Thing class.
Specifically:
public class Things : List<IThing>, IThings
{
}
In this case, you don't have to override the default implementation of GetEnumerator(), the base implementation is already typed correctly for you. This will avoid the overflow that you're currently experiencing and satisfies the test case you provided.

This is a nice example of the need for the language and runtime to understand covariance and contravariance.
In C# 4, you can just use
IEnumerator<IThing> IEnumerable<IThing>.GetEnumerator()
{
return base.GetEnumerator();
}

Seems pretty obvious that this.Cast<IThing>() returns an IEnumerable. Or, at least it does without the implementation of Cast.

I don't know if a question qualifies as an answer but bear with me Im a consultant ;P Why do you wanna implement the GetEnumerator()?
You're deriving from List if you change that to List you get the GetEnumerator for free.
Be aware too that deriving from List is generally a bad idea. you should consider deriving from IEnumerable<()IThings> (as you're already doing which is atm superflurous since List also implements that interface) or if you need the List interface and not only the IEnumerable implement IList and keep a private List object. That way you get full control about the implementation and only expose a design contract (through the implemented interfaces)

Related

Why do I need an explicit interface declaration here? (C#) [duplicate]

The use case is some what like this:
public class SomeClass : ICloneable
{
// Some Code
// Implementing interface method
public object Clone()
{
// Some Clonning Code
}
}
Now my question is Why is it not possible to use "SomeClass(As it is derived from object)" as a return type of Clone() method if we consider the Funda's of Covariance and Contravariance?
Can somebody explain me the reason behind this implementation of Microsoft ????
Let me rephrase the question:
Languages such as C++ allow an overriding method to have a more specific return type than the overridden method. For example, if we have types
abstract class Enclosure {}
class Aquarium : Enclosure {}
abstract class Animal
{
public virtual Enclosure GetEnclosure();
}
then this is not legal in C# but the equivalent code would be legal in C++:
class Fish : Animal
{
public override Aquarium GetEnclosure() { ...
What is this feature of C++ called?
The feature is called "return type covariance". (As another answer points out, it would also be possible to support "formal parameter type contravariance", though C++ does not.)
Why is it not supported in C#?
As I've pointed out many times, we don't have to provide a reason why a feature is not supported; the default state of all features is "not supported". It's only when huge amounts of time and effort are put into making an implementation that a feature becomes supported. Rather, features that are implemented must have reasons for them, and darn good reasons at that considering how much it costs to make them.
That said, there are two big "points against" this feature that are the primary things preventing it from getting done.
The CLR does not support it. In order to make this work we'd basically have to implement the exactly matching method and then make a helper method that calls it. It's doable but it gets to be messy.
Anders thinks it is not a very good language feature. Anders is the Chief Architect and if he thinks it is a bad feature, odds are good its not going to get done. (Now, mind you, we thought that named and optional parameters was not worth the cost either, but that did eventually get done. Sometimes it becomes clear that you do have to grit your teeth and implement a feature that you don't really like the aesthetics of in order to satisfy a real-world demand.)
In short, there are certainly times when it would be useful, and this is a frequently requested feature. However, it's unlikely that we're going to do it. The benefit of the feature does not pay for its costs; it considerably complicates the semantic analysis of methods, and we have no really easy way to implement it.
A non-broken implementation of interface-implementation variance would have to be covariant in the return type and contravariant in the argument types.
For example:
public interface IFoo
{
object Flurp(Array array);
}
public class GoodFoo : IFoo
{
public int Flurp(Array array) { ... }
}
public class NiceFoo : IFoo
{
public object Flurp(IEnumerable enumerable) { ... }
}
Both are legal under the "new" rules, right? But what about this:
public class QuestionableFoo : IFoo
{
public double Flurp(Array array) { ... }
public object Flurp(IEnumerable enumerable) { ... }
}
Kind of hard to tell which implicit implementation is better here. The first one is an exact match for the argument type, but not the return type. The second is an exact match for the return type, but not the argument type. I'm leaning toward the first, because whoever uses the IFoo interface can only ever give it an Array, but it's still not entirely clear.
And this isn't the worst, by far. What if we do this instead:
public class EvilFoo : IFoo
{
public object Flurp(ICollection collection) { ... }
public object Flurp(ICloneable cloneable) { ... }
}
Which one wins the prize? It's a perfectly valid overload, but ICollection and ICloneable have nothing to do with each other and Array implements both of them. I can't see an obvious solution here.
It only gets worse if we start adding overloads to the interface itself:
public interface ISuck
{
Stream Munge(ArrayList list);
Stream Munge(Hashtable ht);
string Munge(NameValueCollection nvc);
object Munge(IEnumerable enumerable);
}
public class HateHateHate : ISuck
{
public FileStream Munge(ICollection collection);
public NetworkStream Munge(IEnumerable enumerable);
public MemoryStream Munge(Hashtable ht);
public Stream Munge(ICloneable cloneable);
public object Munge(object o);
public Stream Munge(IDictionary dic);
}
Good luck trying to unravel this mystery without going insane.
Of course, all of this is moot if you assert that interface implementations should only support return-type variance and not argument-type variance. But almost everyone would consider such a half-implementation to be completely broken and start spamming bug reports, so I don't think that the C# team is going to do it.
I don't know if this is the official reason why it's not supported in C# today, but it should serve as a good example of the kind of "write-only" code that it could lead to, and part of the C# team's design philosophy is to try to prevent developers from writing awful code.
You have to implement an interface's methods exactly as they are in the interface. ICloneable's Clone method returns an object, so your SomeClass must also return an object. You can, however, return a SomeClass instance in SomeClass's Clone method without any problem, but the method definition must match the interface:
public class SomeClass: IClonable
{
// Some Code
//Implementing interface method
Public object Clone()
{
SomeClass ret = new SomeClass();
// copy date from this instance to ret
return ret;
}
}
In terms of explaining the reasons behind C# decisions, Eric Lippert from Microsoft has written much explaining Contra/CoVariance in C#... here's the tag list from his blog:
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
[Edit]
Specific to your question, this might be the right post.. http://blogs.msdn.com/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx
It looks like the kind of thing they could have used generics for, but it seems there is a good reason why they did not.
It is talked about here:
http://bytes.com/topic/c-sharp/answers/469671-generic-icloneable
Basically, a generic interface that would allow:
public class MyClass : IClonable<MyClass>
would also allow:
public class MyClass : IClonable<MyOtherClass>
which doesn’t really provide any benefit, and might confuse things.
According to the C# specification, you must use a method with an identical signature when overriding or implementing an interface method. Keep in mind that Microsoft does not own C#. Their C# compiler is simply their implementation of it. So why would the spec do things this way? I can only guess, but I suspect it was for ease of implementation.

Implementing an interface whereby generics are based on the interface

I am currently refactoring my code so that all important classes implement an interface (for unit testability). I came across a class that implements IComparable (non-templated); something like:
public MyClass : IComparable
{
public int CompareTo(object obj)
{
MyClass cObj = obj as MyClass;
if (cObj == null) { throw new ArgumentException(); }
// etc.
}
}
I'm wanting to interface it out, and use generics while I'm at it; something like this:
public IMyClass : IComparable<IMyClass>
{
// Other methods here
}
public MyClass : IMyClass
{
public CompareTo<IMyClass>(IMyClass other)
{
...
}
// Other methods here
}
But then, ideally, MyClass should implement IComparable<MyClass> (and then subclasses of MyClass should implement IComparable<MySubClass>).
All of this to ask several questions:
What do you think of the approach I described? Is there a better way of doing this refactoring? Is there a point in making MyClass also implement IComparable<MyClass>, or is that pointless since we already implement IComparable<IMyClass>? Any pro-tips or "best"-practices I could be made aware of?
Does it really make sense to have several objects of different types that are all comparable to each other? The language allows this, but I can count on 0 hands the number of times I've had to use it.
I'd recommend using IClass without being IComparable, and just have the derived classes implement IComparable.
P.S. I'm also against adding interfaces "for unit testability". If your program design calls for a factory pattern with interface-only coupling, then by all means code up that level of complexity. But don't abuse the design just to make your tests easier; use Moles instead.
Short answer: it depends.
In your specific example, I would say it is almost always the wrong thing to do to create an unnecessary interface (IMyClass in this case) because it just creates work for you. Rule of thumb: use interfaces only when more than one class implements them. And as you point out this particular interface doesn't even accomplish the goal of making your class directly comparable.
As far as which classes should implement IComparable, generic or otherwise, it depends entirely on what your comparison needs are. If comparison is always done between references to the base class, the derived class doesn't need to implement the interface as it will never be called.

Why do I need IEnumerator.Current in a class implementing IEnumerator<T>?

I have a class that implements IEnumerator<string>. See below:
public class MyClass : IEnumerator<string>
{
public bool MoveNext()
{
//....
}
//Implement other required methods....
//Confusion lies below:
public string Current { get { return this.CurrentLine; } }
//Why do I need to implement IEnumerator.Current?! In my tests, it's not even called during my iteration
object IEnumerator.Current { get { throw new NotImplementedException(); } }
}
Besides the fact that .Current property exists on both the IEnumerator<T> interface and the IEnumerator interface (which IEnumerator<T> inherits), what's the point of implementing it? As seen above it's not even called.
IEnumerator<T> implements IEnumerator, so at the most basic level you have to fulfill the contract.
Specifically as to why - what happens if someone does this:
((IEnumerator)yourInstance).Current
They (usually) should expect to get a loosely-typed copy of the same value/reference returned from IEnumerator<T>'s implementation. So in most cases, just return this.Current and don't worry about it :)
(FYI - returning this.Current is also good practice because it follows DRY and SRP - let the strongly-typed version of Current deal with the implementation details of what Current actually is.)
The reason is that IEnumerator<T> inherits IEnumerator so when you inherit from IEnumerator<T> you implicitly also inherit from IEnumerator. If you advertise an interface you should also provide an implementation for that interface even if you never intend to use it.
The compiler requires you to implement all virtuals because it cannot possibly know which ones will be called when some unanticipated assembly loads your assembly at some point in the unknown future. By inheriting from an interface, you are "signing a contract" which promises that you will implement all its members. The compiler holds you to that agreement so that other assemblies will be able to rely on it.
The purpose of the interface feature is to enable your class to tell any other assembly, any where, any time, "this is what you can ask me to do". If you want to advertise a lesser capability, define a new interface that provides only the partial functionality you want, and implement that instead.
Of course, all of this is industrial-strength stuff. It's more than you need for your code right now. But C# is meant to be useful for doing serious stuff, not just toys.
As for the two different, near-identical overrides: You have to overrides both Current properties because they are essentially different: One is a generic returning T; the other is non-generic returning Object. You can always treat a String reference as a reference to Object, but that doesn't go both ways. And then what about value types? T is not constrained to be a class. Sure, the compiler could hypothetically figure all this out for you and let you off the hook in cases where the two are fungible, but it doesn't, and I'm not convinced it should. If you want C++, you know where to find it.

Why the concept of "Covariance" and "Contravariance" are applicable while implementing the methods of an interface?

The use case is some what like this:
public class SomeClass : ICloneable
{
// Some Code
// Implementing interface method
public object Clone()
{
// Some Clonning Code
}
}
Now my question is Why is it not possible to use "SomeClass(As it is derived from object)" as a return type of Clone() method if we consider the Funda's of Covariance and Contravariance?
Can somebody explain me the reason behind this implementation of Microsoft ????
Let me rephrase the question:
Languages such as C++ allow an overriding method to have a more specific return type than the overridden method. For example, if we have types
abstract class Enclosure {}
class Aquarium : Enclosure {}
abstract class Animal
{
public virtual Enclosure GetEnclosure();
}
then this is not legal in C# but the equivalent code would be legal in C++:
class Fish : Animal
{
public override Aquarium GetEnclosure() { ...
What is this feature of C++ called?
The feature is called "return type covariance". (As another answer points out, it would also be possible to support "formal parameter type contravariance", though C++ does not.)
Why is it not supported in C#?
As I've pointed out many times, we don't have to provide a reason why a feature is not supported; the default state of all features is "not supported". It's only when huge amounts of time and effort are put into making an implementation that a feature becomes supported. Rather, features that are implemented must have reasons for them, and darn good reasons at that considering how much it costs to make them.
That said, there are two big "points against" this feature that are the primary things preventing it from getting done.
The CLR does not support it. In order to make this work we'd basically have to implement the exactly matching method and then make a helper method that calls it. It's doable but it gets to be messy.
Anders thinks it is not a very good language feature. Anders is the Chief Architect and if he thinks it is a bad feature, odds are good its not going to get done. (Now, mind you, we thought that named and optional parameters was not worth the cost either, but that did eventually get done. Sometimes it becomes clear that you do have to grit your teeth and implement a feature that you don't really like the aesthetics of in order to satisfy a real-world demand.)
In short, there are certainly times when it would be useful, and this is a frequently requested feature. However, it's unlikely that we're going to do it. The benefit of the feature does not pay for its costs; it considerably complicates the semantic analysis of methods, and we have no really easy way to implement it.
A non-broken implementation of interface-implementation variance would have to be covariant in the return type and contravariant in the argument types.
For example:
public interface IFoo
{
object Flurp(Array array);
}
public class GoodFoo : IFoo
{
public int Flurp(Array array) { ... }
}
public class NiceFoo : IFoo
{
public object Flurp(IEnumerable enumerable) { ... }
}
Both are legal under the "new" rules, right? But what about this:
public class QuestionableFoo : IFoo
{
public double Flurp(Array array) { ... }
public object Flurp(IEnumerable enumerable) { ... }
}
Kind of hard to tell which implicit implementation is better here. The first one is an exact match for the argument type, but not the return type. The second is an exact match for the return type, but not the argument type. I'm leaning toward the first, because whoever uses the IFoo interface can only ever give it an Array, but it's still not entirely clear.
And this isn't the worst, by far. What if we do this instead:
public class EvilFoo : IFoo
{
public object Flurp(ICollection collection) { ... }
public object Flurp(ICloneable cloneable) { ... }
}
Which one wins the prize? It's a perfectly valid overload, but ICollection and ICloneable have nothing to do with each other and Array implements both of them. I can't see an obvious solution here.
It only gets worse if we start adding overloads to the interface itself:
public interface ISuck
{
Stream Munge(ArrayList list);
Stream Munge(Hashtable ht);
string Munge(NameValueCollection nvc);
object Munge(IEnumerable enumerable);
}
public class HateHateHate : ISuck
{
public FileStream Munge(ICollection collection);
public NetworkStream Munge(IEnumerable enumerable);
public MemoryStream Munge(Hashtable ht);
public Stream Munge(ICloneable cloneable);
public object Munge(object o);
public Stream Munge(IDictionary dic);
}
Good luck trying to unravel this mystery without going insane.
Of course, all of this is moot if you assert that interface implementations should only support return-type variance and not argument-type variance. But almost everyone would consider such a half-implementation to be completely broken and start spamming bug reports, so I don't think that the C# team is going to do it.
I don't know if this is the official reason why it's not supported in C# today, but it should serve as a good example of the kind of "write-only" code that it could lead to, and part of the C# team's design philosophy is to try to prevent developers from writing awful code.
You have to implement an interface's methods exactly as they are in the interface. ICloneable's Clone method returns an object, so your SomeClass must also return an object. You can, however, return a SomeClass instance in SomeClass's Clone method without any problem, but the method definition must match the interface:
public class SomeClass: IClonable
{
// Some Code
//Implementing interface method
Public object Clone()
{
SomeClass ret = new SomeClass();
// copy date from this instance to ret
return ret;
}
}
In terms of explaining the reasons behind C# decisions, Eric Lippert from Microsoft has written much explaining Contra/CoVariance in C#... here's the tag list from his blog:
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
[Edit]
Specific to your question, this might be the right post.. http://blogs.msdn.com/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx
It looks like the kind of thing they could have used generics for, but it seems there is a good reason why they did not.
It is talked about here:
http://bytes.com/topic/c-sharp/answers/469671-generic-icloneable
Basically, a generic interface that would allow:
public class MyClass : IClonable<MyClass>
would also allow:
public class MyClass : IClonable<MyOtherClass>
which doesn’t really provide any benefit, and might confuse things.
According to the C# specification, you must use a method with an identical signature when overriding or implementing an interface method. Keep in mind that Microsoft does not own C#. Their C# compiler is simply their implementation of it. So why would the spec do things this way? I can only guess, but I suspect it was for ease of implementation.

C#: Optional method

I have an object that implements an interface. I want to call on the object's method if it is implemented. What's the best way in doing this?
Update
A few of you mentioned that my question was vague. Sorry about that. When i said "if it is implemented" i meant "if it is callable". Thanks for your answers and effort guys (or girls!). I'm amazed how much developer support there is on this website.
If this really the way you need it to work, an interface is the wrong choice. Instead, you could have an abstract class from which your class derives with a virtual method. Virtual allows it to be overridden, but does not require it. Since a virtual method has an implementation, it cannot be part of an interface.
Not quite sure what you mean by "if it is implemented." If the method is in the interface and your object implements the interface it must implement the method.
If you want to test if an object implements the interface so you can call the method, you can do it like so:
interface IFoo { void Bar(); }
object o = GetObjectThatMayImplementIFoo();
IFoo foo = o as IFoo;
if (foo != null) {
foo.Bar();
}
I think that's what you were asking?
Create two interfaces, and inherit both interfaces where all methods are required. Inherit only one of the interfaces where the optional methods aren't required.
You can also create a base interface, from which all your interface will inherit, for OOP uses.
I think what you're really looking for is a partial method. These are new in .NET 3.5. You simply declare the method as "partial":
partial void OnLoaded();
The method can be called normally:
OnLoaded();
The neat thing is that if the method is not implemented anywhere, the compiler is smart enough not to generate the call.
This was implemented primarily for LINQ to SQL and for Entity Framework; this allows generated code (using partial classes) to define and call methods without knowing whether they are implemented.
Mixing partial methods with interfaces would be interesting (I haven't tried it), but my first try would be declaring a partial method in the interface.
Shouldn't the object's class implement every method of the interface?
If the object's class inherits from an abstract class, it is possible that it might not override("implement") some methods. Perhaps you are mixing the two up in your mind.
As with the other answers, I'm not sure what you mean. The closest that a class implementing an interface can get to not implementing one of the interface methods is throwing a NotImplementedException. The way to handle this is to specifically catch that exception when calling the method. However, the whole point of an interface is to define a contract between classes, so maybe some clarification would help.
My first response is don't do this. It creates conditional logic around the possibility of a method being there, it goes against the statically typeness of C# and breaks a couple of the SOLID principles. My experience tells me this is the wrong path to walk down.
With that said it can be done via Reflection or using the 'is/as' solution wojo demonstrates.
This type of behavior might be better implemented in a dynamic language. It sounds similar to Duck typing. I'm not a dynamic language guy, but if you have unit tests, it may be alright.
You cannot really know if the method is actually implemented (or if the class just has a "dummy" implementation). Therefore, you may use a pattern such as one of the following to find out if a specific method is supported:
-> Have multiple interfaces and see if the class actually implements it; this is probably the cleanest way to deal with it, but it may leave you with a large number of different interfaces, which may not be desirable:
IIntfA = inst as IIntfA;
if (inst != null) {
// inst seems to be implemented
}
-> Use methods in the TryXxx style, which return true if they were successfull (like TryParse() etc.).
-> Use NotImplementedException - but note that catching those is very expensive and should only be used for calls which are performed rarely, or where a missing implementation is not expected. The Stream class works like this, for instance if it cannot be written to (but additionally there is a property telling what the class supports, e.g. IsWritable in the Stream class).
Hey guys, don't forget the "is" keyword :P
You can check if an object implements an interface like this too:
if (inst is IInterface)
{
// you can safely cast it
}
I prefer it that way but of course you could also use the "as" keyword
IInterface a = inst as IInterface;
if (a != null)
{
// use a, already casted
}
Depending on how you're referencing an object, certain members will be visible. An interface might be implicitly defined or explicitly defined, or might be implemented by a derived class and you're using a base class reference. In other words, it's not always immediately evident all the available members on an object.
So if you want to test for implementation of a certain interface (ISomething) by your object (yourObj), one choice is testing the data type, using reflection. Based on the result of this test, you can explicitly cast an implementing object into the interface Type and use its members...
if (yourObj is ISomething)
((ISomething)yourObj).DoSomething();
This is the same thing done another way (more "wordy" using method calls):
if (typeof(ISomething).IsAssignableFrom(yourObj.GetType()))
((ISomething)yourObj).DoSomething();
This sample assumes the ISomething interface is defined as:
public interface ISomething {
void DoSomething();
// other members ...
}
In summary, this code says: if the interface ISomething Is-Assignable-From your object of choice, then your object implements that interface and therefore has those public members.
I don't know if you might be looking for something like this. This uses an attribute that you can flag a method with whether or not it is implemented. Next I added an extension method to the interface to allow for checking if ithe method is implemented. Finally, the code will allow you to ask an object if the method is implemented. I don't like this but it might be what you are looking for.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ConsoleApplication1
{
public static class Program
{
static void Main(string[] args)
{
EmployeeA empA = new EmployeeA();
if (empA.IsImplemented("TestMethod"))
empA.TestMethod();
EmployeeB empB = new EmployeeB();
if (empB.IsImplemented("TestMethod"))
empB.TestMethod();
Console.ReadLine();
}
public static bool IsImplemented(this IEmp emp, string methodName)
{
ImplementedAttribute impAtt;
MethodInfo info = emp.GetType().GetMethod(methodName);
impAtt = Attribute.GetCustomAttribute(info, typeof(ImplementedAttribute), false)
as ImplementedAttribute;
return (impAtt == null) ? true : impAtt.Implemented;
}
}
public class EmployeeA : IEmp
{
#region IEmp Members
[Implemented(false)]
public void TestMethod()
{
Console.WriteLine("Inside of EmployeeA");
}
#endregion
}
public class EmployeeB : IEmp
{
#region IEmp Members
[Implemented(true)]
public void TestMethod()
{
Console.WriteLine("Inside of EmployeeB");
}
#endregion
}
public class ImplementedAttribute : Attribute
{
public bool Implemented { get; set; }
public ImplementedAttribute():this(true)
{
}
public ImplementedAttribute(bool implemented)
{
Implemented = implemented;
}
}
public interface IEmp
{
void TestMethod();
}
}
EDIT: After original author reworded question, you definitely just want to implement the interface guranteeing the method does exist. I will leave above code for curiosity sake.

Categories

Resources