Class or ArrayList? - c#

I have made a weather app that receives information from an api. I have a class like that:
public class Forecast
{
public DateTime date { get; set; }
public string day_name { get; set; }
public string symbol { get; set; }
public int degree { get; set; }
public int degreemax { get; set; }
public int degreemin { get; set; }
public string condition { get; set; }
}
The class helps me to hold data. Also I can hold data with ArrayList, not necessarily class. I know that I should use classes. However, I am wondering which one is more efficient.
Thanks a lot.

In your scenario, anytime I would prefer a class over an ArrayList. The following are the positives I can think of right now
Intellisense - you will have date, etc in intellisnse. Whereas in arraylist you would need to remember on which location you have entered what data
boxing-unboxing - arraylist adds values in object so if you are putting int values, they will be boxed
Multiple Forecasts - If you want to store many Forcasts then it is not possible using arraylist or at least it will be 1 hell of a time for you to maintain it. It can be easily implemented with classes using List<yourClass>
Performance - Class is anytime better performing than ArrayList
More functionality - You can add methods to a class to extend its functionality like some calculations, etc. To have more functionality to ArrayList you would need to create a custom class inheriting from ArrayList and write your functionality there so ultimately you are using a class only.
OOPS concepts - All OOPS concept apply to a class like inheritance hence extending the functionality to other classes, etc. Not possible with ArrayList
Hope this helps.

Related

What is a good design pattern to avoid having to use a global variable at the top your main form?

Every time I talk to experienced programmers, they talk about having global variables being a bad practice because of debugging or security exploits. I have a simple List of strings I want to load from a a textfile and access across different methods in my form. Before, I would simply initialize said variable at the top, inside of my form class and use it across methods. I always try to reduce that practice when I can and only initialize those variables when I really need them. Is it a bad practice to do this or do more experienced programmers do this too? Is there a standard design pattern method of doing this so you don't have to use "global variables" at the top of your form?
As you're talking about C# and it's a fully-object-oriented programming language, there's no way to declare global variables.
In an OOP language like C#, a bad practice can be simulating global variables using static classes:
public static class Global
{
public static string Value1 { get; set; }
public static int Value2 { get; set; }
}
...to later get or set these values from other classes. Definitely, this a bad practice because state should be held by specific and meaningful objects.
Usually, in a perfect/ideal OOP solution, you should pass such values from class to class using constructors:
public class X
{
public int Value1 { get; set; }
public void DoStuff()
{
Y y = new Y(this);
y.DoChildStuff();
}
}
public class Y
{
public class Y(X parent)
{
Parent = parent;
}
public X Parent { get; }
public void DoChildStuff()
{
// Do some stuff with Parent
}
}
Or also, you might pass states providing arguments to some method:
public class Y
{
public void DoChildStuff(X parent)
{
// Do some stuff with "parent"
}
}
Since you're passing states with reference types, if any of the methods in the chain decide to change Parent.Value1 with another value, all objects holding a reference to the same X object will get the new X.Value1.
Some fellows might argue that we usually build configuration objects which own a lot of properties accessed by other arbitrary objects, right? BTW, configuration is a concept per se, isn't it? And we usually categorize configuration values using composition:
public class ApplicationConfiguration
{
public DatabaseConfiguration Database { get; } = new DatabaseConfiguration();
public StorageConfiguration Storage { get; } = new StorageConfiguration();
}
public class DatabaseConfiguration
{
public string ConnectionString { get; set; }
}
public class StorageConfiguration
{
public string TemporalFileDirectoryPath { get; set; }
public string BinaryDirectoryPath { get; set; }
}
So later we inject the application configuration wherever we need it:
// Please note that it's a VERY hypothetical example, don't take
// it as an actual advise on how to implement a data mapper!!
public class DataMapper
{
public DataMapper(ApplicationConfiguration appConfig)
{
AppConfig = appConfig;
}
public ApplicationConfiguration AppConfig { get; }
private IDbConnection Connection { get; }
public void Connect()
{
// We access the configured connection string
// from the application configuration object
Connection = new SqlConnection(AppConfig.Database.ConnectionString);
Connection.Open();
}
}
In summary, and since I love comparing real-world and programming use cases, imagine that you never clean your room and you would use a single box to store every tool you might need some day. One day you need a screwdriver from the whole box, and you know that's inside it... But you need to throw everything in the box to the ground and work out the mess prior to find the priceless screwdriver to complete some home task.
Or imagine that you've bought a toolbox to store your tools in order, and once you need a screwdriver, you know that's in the toolbox and in the section where you store your screwdrivers.
You know that the second approach is the most mind-friendly. That is, when you develop software, you need to design mind-friendly architectures rather than a big mess of unrelated data and behaviors working together.

Generics by context

I started writing this as a real question, but I kept thinking of answers along the way, thought I would post it anyway to see if there were any other solutions
I can think of two examples in which generics become an unecessary pain, and I wonder if there is a solution.
Example 1
public class SomeClass<TDbConnection, TDbTransaction>
{
}
Now for any of us it's obvious - The DbTransaction, and DbConnection implementations will always be used in pairs - be it SqlConnection and SqlTransaction or OracleConnection and OracleTransaction
besides the fact that there is no way to make sure that the types make sense (nothing stops me from creating SomeClass<SqlConnection, OracleTransaction> when SomeClass uses three or four arguments that there types are inferable by context*, it becomes an unnecessary waste of time to instantiate each type.
*in this example, I am not sure how the framework can know, but you get my point? anyway the next example is more relevant
Example 2
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class SomeClassUsingPOCOAndId<TPoco, TKey>
where TPoco : IPoco<TKey>
{
}
In this example I managed to force the use of the correct TKey in instantiation, but why can't I just call new SomeClass<IPoco<int>>() or new SomeClass<SomePoco>() I mean the TKey is inferable.
Possible Solutions
I could drop the Generics, and in some cases it makes sense (like the first example). In others not so much, and creates either a memory or runtime overhead (unnecessarily creating of fields, or casting) or unnecessary code repeat.
The other solution I thought of was creating something like this
public interface IPoco<TKey>
{
public TKey Id { get; set; }
}
public class SomePOCO : IPoco<int>
{
public int Id { get; set; }
}
public class PocoContext<TPoco, TKey>
where TPoco : IPoco<TKey>
{
TKey Key { get; set; }
TPoco Poco { get; set; }
public PocoContext(TPoco poco)
{
Key = poco.Key;
Poco = poco;
}
}
public class SomeClassUsingPOCOAndId<TPocoContext>
{
}
This allows me to reduce the amount of code required for instantiation - but depending on my usage of the pocos - it could become really time consuming to create a context for each type.
Now I am wondering - isn't there a way to simplify this process? maybe by some sort of synthetic sugar? What would it take to implement it on C# 7 or 8?

Using Clone() to duplicate an ASP.NET MVC / EntityFramework model object

I've read this question about using Clone() and want to know if what I'm after will be achieved. My understanding from reading that question is that Clone() does a shallow copy, however reading elsewhere led me to believe differently, and now I'm confused.
Our project has a class Rule that has an ICollection<ICondition> Conditions. We'd like to provide users with a shortcut method to duplicate an existing Condition and modify it rather than start from scratch. To that end, we're providing a Copy To New button.
ICondition looks like this:
interface ICondition
{
long ID { get; set; }
string Description { get; set; }
DateTime EffectiveDate { get; set; }
string IfStatement { get; set; }
string PriceVersion { get; set; }
PriceDetail Pricing { get; set; }
bool StandardOption { get; set; }
}
Given what I've read about Clone(), I'm fairly confident it would work the way I expect by using ICondition newCondition = conditionToCopy.Clone(), though I'm unsure if Pricing would be duplicated correctly, since it's a complex data type.
So, the first part of my question is, "will this work?" I would just try it and see, however ICondition (or really its underlying Condition) doesn't seem to provide a method for Clone(), which leads me to the second part of my question: can I leverage IClonable to enable this functionality? If so, where?
Is this the way?
public static class Condition : IClonable
{
...
public Condition Clone(Condition conditionToClone)
{
return new Condition
{
Description = this.Description,
EffectiveDate = this.EffectiveDate,
IfStatement = this.IfStatement,
PriceVersion = this.PriceVersion,
Pricing = this.Pricing,
StandardOption = this.StandardOption
}
}
}
And, given that as the answer, is there any utility to declaring IClonable as the interface? Does it add any value?
Update:
Based on the below answer, I decided to do this, which at least builds (and hopefully runs; haven't tried it yet):
public class Condition
{
...
public Condition Clone()
{
return (Condition)base.MemberwiseClone();
}
}
I still don't see the need for ICloneable, so have left it out. The compiler was complaining about it anyway, something about the base class not being object.
There are couple of things. First Condition class should not be static. Second, PriceDetail class [Property pricing], Also need to impleemnt ICloneable. Instance class will allow base.MemberWiseClone() method.
public class Condition : ICloneable
{
public object Clone()
{
base.MemberwiseClone();
}
}

Is this candidate for abstract class

let's say that I want to collect in one place all common properties and behaviors for all sports. I was thinking to use SportBase as abstract class for this purpose but I'm not sure. I'm trying to understand the differences between Abstract vs Interface usage on this example.
Every sport should have following properties
DateTime Started;
DateTime Ended;
string Name;
What if I declare these properties like integers and later on I decide to use Game object as separated entity like Game StartGame. I do not see clearly which approach to use with high level of abstraction to reduce pain on later modification (this modification can have adding new properties, new behaviors, etc.)
Thanks
if you only have properties and empty methods an interface might be your better choice. if you have some actual code then abstract class is your only option. also remember that you can inherit only one abstract class but implement multiple interfaces.
You can use an interface to provide a contract to code to.
public interface ISportsEvent
{
DateTime Start { get; set; }
DateTime End { get; set; }
string Name { get; set; }
}
but that doesn't give you a reusable implementation
As a general rule you should prefer composition over inheritance.
So its often better to do something like this
public interface EventDetails
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string Name { get; set; }
}
public class SportingEvent
{
public EventDetails Details {get;set;}
}
now this is a bit rough but you can see what I'm getting at.
No, I wouldn't do that. You'll end up creating an abstract God class, which has way to many responsabilities.
I personally would probably make it an abstract class, since not only will your sports share some fields, but they might share some logic too.
Interfaces aren't for seperating out duplicate code, but they're purely for polymorphism.
All an interface does is guarantee that your class will act a certain way. If you plan on putting logic in your base class than you want an abstract class.

protobuf-net and interface support

This question directly in large part to the protobuf-net maintainer(s) but anyone else please comment.
I was trying to serialize a class that contains a property which has an interface type, ie:
[DataContract]
public class SampleDataClass
{
[DataMember(Order=1)]
public int Field1 { get; set; }
[DataMember(Order = 2)]
public IPayload Payload { get; set; }
}
[ProtoContract]
[ProtoInclude(1, typeof(Payload))]
public interface IPayload
{
int Field4 { get; set; }
}
[DataContract]
public class Payload : IPayload
{
[DataMember(Order = 1)]
public int Field4 { get; set; }
}
I have managed to get this to work by changing the source of v1 of protobuf-net.
I did not see any problem with this approach as long as ProtoInclude is defined for the interface.
Clearly to get this to compile I had to allow ProtoContract and ProtoInclude to be decorated on interfaces, plus a few other changes here and there. (note, I would have used DataContract/KnownType however these attributes are also not able to be decorated on interfaces)
Can you please comment on possible shortcomings?
The main glitch I can see is that in terms of payload this moves the data into a sub-message. I have some similar designs around v2 that hopefully get around this, keeping most values in the primary message. For sanity reasons, I mainly had just v2 in mind for this change (since the two implementations would be separate, and v2 has a much better type model).
However, it should be possible to support both modes of use. If you want to send it as a patch for v1 (with the same license etc) I'd happily take a look :)
This is available as a standard feature of v2

Categories

Resources