I'm in the middle of creating a new library, and as I was building it something seemed a little odd.
Here's the code:
namespace traditional_poker
{
public class poker
{
public class hand
{
public String Name
{
get; set;
}
public String[] cards
{
get; set;
}
}
List<hand> players;
public void AddPlayer(String name)
{
hand newHand = new hand();
newHand.Name = name;
players.Add(newHand);
}
}
}
I have List<hand> players inside the Library itself, which means the library is storing data (albeit temporarily).
Is this bad practice?
Is there a better way to do this?
Or is the way I'm doing it completely legitimate?
It all depends on the way you want to tackle the problem.
If you want to have the data temporarily then it is Ok, If you want to save your data between different application instances or across different sessions then you should use a data persistent tool (filing, databases, ...)
namespace traditional_poker
{
public class poker
{
public class hand // use PascalCaseNamingConvention
{
public String Name
{
get; set;
}
public String[] cards // use PascalCaseNamingConvention
{
get; set;
}
}
List<hand> players;
public void AddPlayer(String name)
{
hand newHand = new hand();
newHand.Name = name;
players.Add(newHand); //null reference exception here! you should initialize players
}
}
}
The library is not storing data.
It offers functionality, using classes, which have fields. These classes are instantiated by an application using them, in the application memory space.
If it were bad practice to have data 'stored' in libraries, then libraries would not have classes or variables, and be severely limited.
Related
I have a few business objects that have to be used together to get a specific outcome. Take a look at the following very simplyfied example for reference.
My question is: how do I get a reference to the agent using DI in the Station class ? I mostly prefer constructor injection, but that is not possible the Station class already has a stationCode as a required item.
Any ideas ?
Usage:
var station1 = new Station("xx");
var station2 = new Station("yy");
var route = new Route(station1, station2);
var length = route.GetLength();
public class Location
{
public int Position {get; set;}
}
public interface IAgent
{
Location GetLocation(string stationCode);
}
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public Location GetLocation()
{
// issue here: how to get a reference to the agent instance using DI
_agent.GetLocation(_stationCode);
}
}
public class Route
{
private Station _station1;
private Station _station2;
public Route(Station station1, Station station2)
{
_station1 = station1;
_station2 = station2;
}
public int GetLength()
{
var location1 = _station1.GetLocation();
var location2 = _station2.GetLocation();
result = location2.Position - location1.Position;
return result;
}
}
Your classes seem to be having an identity crisis. When using DI, you should have just 2 types of classes to deal with - injectables and newables. Your Station class seems like a kludge because it both provides a service (has dependencies) and has state. To make your classes DI-friendly, you should design classes that only provide state to classes that only do something with the state (services).
Route
This class is injectable - that is, it should be wired from the DI container.
public interface IRoute
{
int GetLength(Station station1, Station station2);
}
public class Route : IRoute
{
private readonly IAgent _agent;
public Route(IAgent agent)
{
if (agent == null) throw new ArgumentNullException("agent");
_agent = agent;
}
public int GetLength(Station station1, Station station2)
{
var location1 = _agent.GetLocation(station1.StationCode);
var location2 = _agent.GetLocation(station2.StationCode);
result = location2.Position - location1.Position;
return result;
}
}
Station
This class is newable - that is, you should always use the new keyword to instantiate it.
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public string StationCode
{
get { return _stationCode; }
// Optional: provide setter here
}
}
Usage
var station1 = new Station("xx");
var station2 = new Station("yy");
// IRoute is injected where you need to make the calculation
var length = _route.GetLength(station1, station2);
Perhaps it would be better to rename Route to something more appropriate, since it does not provide a route, it calculates the route length.
Frankly, if your Station class doesn't have any other state than a single string variable, it would probably make more sense to eliminate the class and just use strings for station1 and station2. But this is mostly just a matter of personal taste.
The concept of two types of classes to deal with, injectables and newables, is a good idea. But when newables should contain only limited business logic, you are drifting away from pure object-oriented concepts. When you write code for a complex domain model, your newable business classes contain both business logic and data. That´s also the intention of the question, I assume. The Station and Route classes are simple examples that contain much more logic and data in reality.
So I would suggest to have better separation of concerns, by separating code for storage from you business logic. I see two common solutions for this.
When data is loaded in memory, a separate StationStore class is an injectable that loads stations and stores them in the context of the business domain, eg. in a static property:
public IEnumarable<Station> Station.Store { get; internal set; }
All DI code can be hidden in a business base class. It´s less disturbing to put DI dependencies there. So an agent can be resolved in the generic base class based on the template types provided.
public class Station : BusinessClass<Station, StationAgent>
{
public string StationCode { get; internal set; }
public Location Location { get; internal set; }
public Station(string stationCode)
{
base.Load(stationCode, this);
}
}
I'm very new in C# and i need some help to use nested classes on my "Hello World" proyect.
I'm trying to create a class callable using class1.subclass1.function(args...) (to create groups of related functions), and I've done something that is working but I think that is not the best way to do it.
My code needs to share a variable between principal class and nested classes (a db handle), and I'm using and argument at class initialization to do it.
namespace SameAsPrincipal
{
public class class1
{
public SQLiteConnection handle = null;
public _subclass1 subclass = null;
public class1(string db_file)
{
handle = new SQLiteConnection(db_file);
subclass1 = new _subclass1(handle);
}
public _subclass1
{
private SQLiteConnection handle = null;
public _subclass1(SQLiteConnection handle)
{
this.handle = handle;
}
public void function(args...)
{
//Do something here
}
}
}
}
Someone knows a better way to create nested classes and share objects between main and nested?
Thanks!!
I am unclear as to why you would want to use a nested class in this instance. The way you have it written, the subclass is all you need. If you want multiple methods (or as you called them "functions") just add your methods.
Is there some hidden reason you would want to use nested classes here? As a general rule, nested classes are rarely needed.
namespace SameAsPrincipal
{
public class Class1
{
private SQLiteConnection handle;
public Class1(string db_file)
{
handle = new SQLiteConnection(db_file);
}
public int AddRecord(Record record)
{
// use handle to add record and get record Id
return record.Id;
}
public void DeleteRecord(int id)
{
// Use handle to delete record
}
}
}
When you instantiate the object you will pass in your db_file and the connection object will be created. Then every method could use that connection object when they are called. However it is usually a better idea to create the connection for each method when it is called and disposing of the connection as soon as you the operation is completed. This, of course, depends on your operations and if they are transnational. For the most part using a "using" block to instantiate your connection is a good way to use connection objects. The sooner you release the connection the sooner the machine will reuse that connection, you can lookup connection pooling to learn more.
Here is an example method that is using the "using" to add a person using a stored procedure:
public int AddPerson(Person person)
{
using (var connection = new SQLiteConnection(dbFile))
{
connection.Open();
using (var command = new SQLiteCommand("spAddPerson",connection))
{
command.CommandType = CommandType.StoredProcedure;
var idParameter = new SQLiteParameter("#Id", DbType.Int32);
idParameter.Direction = ParameterDirection.Output;
command.Parameters.Add(idParameter);
command.Parameters.AddWithValue("#FirstName", person.FirstName);
command.Parameters.AddWithValue("#LirstName", person.LastName);
command.ExecuteNonQuery();
}
}
return person.Id;
}
edit: In regard to your comment below
A few things:
Use namespaces not a parent class to group classes.
Instead of sub-classes you should just add all the database methods to the database class and create classes to model your objects.
Each class should be in it's own file
The namespace parts are ..[]* I.E. Music class has the namespace YourApplication.YourProject.Models - inside the YourProject project, within a first level folder named Music you will find a file named Music.cs and with in that file you will find your music class. This is not a requirement, the compiler does not care about structure like that. It will only make your life easier when you start to get more code developed.
Here is an example of the code structure I am speaking of (remember each of these sections is it's own file)
Create a folder at the root of your project called Models. In this Models folder create a file named Music.cs
namespace YourApplication.YourProject.Models
{
public class Music
{
public int Id { get; set; }
public string Title { get; set; }
public double Length { get; set; }
public string Artist { get; set; }
public string Album { get; set; }
}
}
In this same (Models) folder create a file called Film.cs
namespace YourApplication.YourProject.Models
{
public class Film
{
public int Id { get; set; }
public string Title { get; set; }
public double Length { get; set; }
public string Director { get; set; }
public string[] Actors { get; set; }
}
}
Now back at the project root (no longer in Models folder) create a new folder called Persistence.
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using YourApplication.YourProject.Models;
namespace YourApplication.YourProject.Persistence
{
public static class DatabaseActions
{
public static string dbFile;
public static Music[] ListMusic()
{
var musicList = new List<Music>();
// database call to get all music
using (var connection = new SQLiteConnection(dbFile))
{
connection.Open();
using (var command = new SQLiteCommand("spGetMusic", connection))
{
var reader = command.ExecuteReader();
// The try finally blocks are not strictly needed as these will are suppose to be called upon disposal
try
{
// loop through records creating music objects
while (reader.Read())
{
var music = new Music();
music.Id = reader.GetInt32(0);
music.Title = reader.GetString(1);
musicList.Add(music);
}
}
finally
{
reader.Close();
connection.Close();
}
}
}
return musicList.ToArray();
}
public static int SaveMusic(Music music)
{
if (music.Id == 0)
{
// database stuff - getting the newly created database id
}
else
{
// database calls to update record
}
return music.Id;
}
public static int SaveFilm(Film film)
{
if (film.Id == 0)
{
// database stuff - getting the newly created database id
}
else
{
// database calls to update record
}
return film.Id;
}
public static Music GetMusic(int id)
{
var music = new Music();
// database call and setting of values on music
return music;
}
public static Film GetFilm(int id)
{
var film = new Film();
// database call and setting of values on music
return film;
}
}
}
Now finally create a file on the root called WorkHarness.cs
using System;
using YourApplication.YourProject.Persistence;
namespace YourApplication.YourProject
{
public class WorkHarness
{
public void Initialize()
{
DatabaseActions.dbFile = "your db file";
}
public void ShowMusicList()
{
// list the id and title so user can select by Id
foreach (var music in DatabaseActions.ListMusic())
{
Console.WriteLine("{0,-10}{1}",music.Id,music.Title);
}
}
public void DisplayMusicItem(int id)
{
var music = DatabaseActions.GetMusic(id);
Console.WriteLine("Title: " + music.Title);
Console.WriteLine("Length: " + music.Length);
Console.WriteLine("Artist: " + music.Artist);
Console.WriteLine("Album: " + music.Album);
}
}
}
Without more context as to what the specific application is, it's hard to tell if it's appropriate or not. I agree with the previous answer that it is generally more correct to have separate classes. Your class B can still take a DB handle reference in its constructor, and class A can even pass it to it. That's fine. It's not so much that they are sharing the variable as that they both have a reference to the same DB handle.
The only time I've ever seen sub/inner classes and not thought it was weird was for like simple data objects that are only ever used within the parent class (although they may be referenced outside). For example, if I made a linked list class, I may choose to have the node class be an inner class. For just grouping functionality, regular classes should do that.
Namespaces can also be used for further grouping. For example, maybe all my text operations are in a "MyApp.Text" namespace, but then they are further grouped into classes like "NumberUtils", "NameUtils", and "ZipUtils".
Instead of nesting the objects, create two classes (at the same scope) and have one use the other, such as this:
public class ClassA
{
public ClassB InstanceOfClassB { get; set; }
public ClassA()
{
InstanceOfClassB = new ClassB();
}
//More code here
}
public class ClassB
{
//Code here
}
Using Nested classes in a HelloWorld project? Not a good sign!!
I would suggest not to use nested types Unless you know what you're doing and you have very good explanation to give when asked. Also a note of advice by .NET Framework Guidelines which explicitly recommend against creating public nested classes.
For data sharing in Object oriented programming we have inheritance feature which is the best way to share data/members access across classes based on relationship/association.
to create groups of related functions
As #Nex Terren suggested (with a little modification), you can do something like this, here your Principle class will work as Factory and different classes will provide Aggregation of related functions by their instance
public class PrincipleClass
{
public ClassB InstanceOfClassB { get; private set; }
public ClassA InstanceOfClassA { get; private set; }
public PrincipleClass(string db_file)
{
InstanceOfClassA = new ClassA(new SQLiteConnection(db_file));
InstanceOfClassB = new ClassB();
}
//More code here
}
public class ClassA
{
public ClassA(SQLiteConnection handle)
{
// your code here
}
public void FunctionOfA1() { }
public void FunctionOfA2() { }
}
public class ClassB
{
public void FunctionOfB1() { }
public void FunctionOfB2() { }
}
Now you'll have your group of function together like
new PrincipleClass.InstanceOfClassA.FunctionOfA1();
new PrincipleClass.InstanceOfClassB.FunctionOfB1();
Note - This may also not be a best solution but this is way better than using Nested types.
I've two Classes
public class DemoProperty
{
public int ID { get; set; }
public string Title { get; set; }
public string MenuCode { get; set; }
public string OriginalURL { get; set; }
}
public class MyCommonProperties
{
private static List<DemoProperty> _DemoList;
public static List<DemoProperty> DemoList
{
get { return _DemoList; }
set { _DemoList = value; }
}
}
My need is to keep some common data throughout the project.For that I've using an application variable and it holds a Dictionary<string,List<DemoProperty>>.
Global.asx
void Application_Start(object sender, EventArgs e)
{
Application["DemoProperty"] = new Dictionary<string,List<DemoProperty>>();
MyCommonProperties.DemoList= (Dictionary<string,List<DemoProperty>>)Application["CommonProperties"];
}
Actually I don't know more about its demerits. If it is a bad idea could you please suggest me a good one.
What the static keyword ensures, is that the specific property / class exists only once in your application.
If this is bad or not is a very general question to which the answer unfortunately seems to be "it depends". Ultimately it is a question how you want to design you program.
Making something static can however make automatic testing harder, because you can not easily decouple your program into smaller testable parts (as all parts directly interact with your static data). It also makes reading the code harder, because it could be hard to understand when and what modifies the global data.
I will try an example to underline this:
class Data {
public static string Entry;
}
class Operations {
void SetOne() {
Data.Entry = "one";
}
}
With this example, for someone calling SetOne() it might be non-obvious that the method actually sets something in Data.
Another approach could be:
class Data {
public string Entry;
}
class Operations {
void SetOne(Data data) {
data.Entry = "one";
}
}
Now for the caller its is more obvious that Data is used in some way by the method, because the call now looks like SetOne(data).
In my humble personal experience static was almost never a good idea. While it might make things quicker in the short run, its drawbacks concerning readability & testability of your code are usually too big to ignore.
first of all I'm a rookie in Unity3D and especally in programming. At this moment i try diffrent things and study different documentations to create an economy simulation game.
So please be merciful to me if i dont understand your solutions instantly ;)
I need to access a twodimensional List from another script.
In Script1 I use a Class to make the 2D
public class OrderArray : MonoBehaviour
{
List<Order> orders;
public class Order
{
public string company{ get; set; }
public string date{ get; set; }
public int quantity{ get; set; }
public string deliverdate{ get; set; }
}
void Start()
{
orders= new List<Order>();
orders.Add(new Order
{ company = "Woodpecker Corp",
date = "21.11.2014",
quantity= 250,
deliverdate= "29.11.2014" });
// To access the Data in the list Im using:
Order order1= orders[0];;
Debug.Log(order1.company)
}
So far so good. Script1 runs good for me.
Now how can I access "order1.company" for example from a different Script on the same GameObject?
I knwo how I can access the variable in Script1 und Class Script in generall but I cant make it to accsess the variables in class "Order".
My result of Script2 till now
public class menu : MonoBehaviour
{
OrderArray orderarray;
Orderarray.Order orderclass;
void start()
{
orderarray= gameObject.GetComponent<OrderArray>();
}
Now I have access to the class OrderArray but I dont know how can i access the class Order inside OrderArray.
Maybe you could give me an approuch to solution or an example code I can transfer for my problem. Thank you.
You can extend your OrderArray with a GetOrderByIndex method:
public Order GetOrderByIndex(int index){
return orders[index];
}
You could use it in your start like this:
void start()
{
orderarray= gameObject.GetComponent<OrderArray>();
Order order1 = orderarray.GetOrderByIndex(0);
//do what you want with order1
}
Doing something like Mark Smit mentioned is probably best. One thing you should consider though is making "Order" a struct instead of a class since it doesn't hold a whole lot of data and you'll have a bunch of them I'd imagine. For further information take a look at this. And add a constructor to "Order" for easier creation of a new one ->
new Order("Woodpecker Corp", "21.11.2014", 250, "29.11.2014")
So let's say I have a Clone object with these properties. Clone might have different mass or name based on the file it was loaded from, but these values never change at runtime. However, Clone instances to have some autonomy and properties which do change per instance, so they can't all be the same instance.
public class Clone
{
public float Mass { get; protected set; }
public string Name { get; protected set; }
public Clone(string filePath)
{
Name = //read name from file
Mass = //read mass from file
}
}
Now, what I want to know is, what are the benefits and drawbacks (if any) of doing this instead:
public class CloneInfo
{
public float Mass;
}
public static class Database
{
public static Dictionary<string, CloneInfo> Lookup;
[...load whole dictionary from files...]
}
public class Clone
{
public string Name { get; protected set; }
public float Mass { get { return Database.Lookup[Name].Mass; } }
public Clone(string name)
{
Name = name;
}
}
With this 'redirecting' method, I keep the simple syntax of Clone.Mass, but don't have to store a Mass value for each instance. Since I've got thousands of clones wandering about, this is a good thing. I'm mainly interested in 'redirecting' because of the syntax. I realize that I could simply manually do the database lookup every time I wanted a particular clone's mass, but I'd rather keep the usage of the class nice and straightforward. Is there any drawback to this? Is the property going to be slower than direct lookup in the static database? Does the property take up any space in a Clone instance?
Or, perhaps, is this a use case C# already has an answer for which I'm not aware of? Seems like write-once properties which are common among many instances might be somewhere in this beautiful language.
If all the clones of a certain type have the same mass, that sounds like a job for subclassing:
class Clone
{
public abstract float Mass { get; }
}
class HeavyClone : Clone
{
public override float Mass { get { return 12345.6; } }
}
class LightClone : Clone
{
public override float Mass { get { return 1.23456; } }
}
More to the point of your question: if you are more constrained by memory than by processing time, your approach may give some benefit. If memory is plentiful, and cache performance is not an issue, the approach you suggest probably has little value. It certainly seems to complicate the code quite a bit.
The usual advice is: write simple code, measure the performance, and, if the performance is inadequate, address the performance bottlenecks. That way, you only have complicated code in places where it actually helps your application's performance.
Another thought: instead of having have the clone index into the dictionary with the Name string, why not just have a CloneInfo field:
public class CloneInfo
{
public float Mass;
}
public class Clone
{
private CloneInfo _info;
public float Mass { get { return _info.Mass; } }
public Clone(CloneInfo info)
{
_info = info;
}
}
Suppose that we have a lot of accesses to Mass property. If in each access you try to load the Mass value from database, it can be a very heavy duty for your application and here will be a bottleneck. If the Mass value can be cached in the object, you can easily load it for once and keep it for further usages.