How to remedy OutOfMemory exception with impossibly long string in c#? - c#

I got an assignment where I have to come up with a code that continues to create unbelievably long strings and I can't figure out how to get around the issue of simply running out of memory by going beyond the limits of a simple string.
The program asks for the following from the user:
A: string that will be its first "real" input (e.g. "a", "asdf", etc.)
B: "base" string with special characters that can be substituted by A (e.g. "%n%", "%abc%def%, %%asd%tr, etc.)
C: number of times the program should run (up to 1 billion)
D: first index of a character from the final string
E: last index of a char from the final string - these are to return to the user with something.
The catch is, with every iteration, A should be updated to whatever output is produced when substituting it into B, and then it's used as an input again.
An example would be 1) ana (A: a, B: %n%) 2) ananana (A: ana, B: %n%) 3) ananananananana (A: ananana, B: %n%) etcetc, and then with D & E being 3 & 7 respectively, the final output would be anana.
Another would be with A: x, B: %a%b%c%, C: 999999999, D: 33, E: 65 --> xaxbxcxaxaxbxcxbxaxbxcxcxaxbxcxbx
One more: A: abcdef, B: %%, C:500, D: 3, E: 22 --> cdefabcdefabcdefabcdef
And like a simple one, A: hi, B: %hey, C: 10, D: 10, E: 20 --> eyheyheyhey
I've been trying to solve it by creating a separate class and running what I think is a form of recursion (although I'm not 100% sure, I'm very much a beginner) but despite my best efforts, I keep getting the OOM error once the string reaches what I assume must be past a string's limit. Maybe I've been trying to approach the whole problem from the wrong angle? But at this point I can't envision a different path I could've taken towards a solution.
Here's what I have so far - would really appreciate any help from anyone!
class Program
{
static void Main(string[] args)
{
BehindTheScenes trial = new BehindTheScenes(Console.ReadLine(), Console.ReadLine(),
int.Parse(Console.ReadLine()), int.Parse(Console.ReadLine()), int.Parse(Console.ReadLine()));
trial.ReWrite();
Console.WriteLine(trial.Display());
Console.ReadLine();
}
}
class BehindTheScenes
{
public string InAndOut { get; set; }
public string specialchar { get; set; }
public int no_of_times { get; set; }
public int min { get; set; }
public int max { get; set; }
public int counter { get; set; }
public BehindTheScenes(string substitute, string specialchar, int no_of_times, int min, int max)
{
this.InAndOut = substitute;
this.specialchar = specialchar;
this.no_of_times = no_of_times;
this.min = min;
this.max = max;
this.counter = 0;
}
public void ReWrite()
{
if (this.specialchar.Contains("$"))
{
string temp = "";
while (counter < this.no_of_times)
{
temp = this.specialchar.Replace("$", this.InAndOut);
this.InAndOut = temp;
counter++;
}
}
}
public string Display()
{
int total_length = this.max - this.min + 1;
string dash = new string('-', 99);
string final = "";
if (!this.specialchar.Contains("$"))
{
if (this.min > this.specialchar.Length)
{
return dash.Substring(0, total_length);
}
else
{
final = string.Concat(this.specialchar, dash);
return final.Substring(this.min - 1, total_length);
}
}
if (this.max > this.InAndOut.Length)
{
final = string.Concat(this.InAndOut, dash);
return final.Substring(this.min - 1, total_length);
}
else
{
return this.InAndOut.Substring(this.min - 1, total_length);
}
}
}

Related

Best way to write multiple constructor overloads in C#

I am learning C# and made a simple "Player" class. But I struggle having multiple overload.
Here's my best solution but I feel like it could be done simpler/better.
class Player : Entity
{
public Player() {
Name = "Player";
XP = 0;
LVL = 1;
XPToLvlUp = 10;
XpRank = 10;
}
public Player(string name) : this() {
Name = name;
}
public Player(string name, int _Hp, int _Mp) : this(name) {
HP = _Hp;
MP = _Mp;
}
public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl) : this(name, _Hp, _Mp) {
XP = _Xp;
LVL = _Lvl;
}
public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl, int XpByRank) : this(name, _Hp, _Mp, _Xp, _Lvl) {
XpRank = XpByRank;
}
//deleted code for better reading
private int XPToLvlUp;
private int XpRank;
public int XP;
public int LVL;
public string Name;
}
Is it good and if not please tell me why.
Thanks for your responses!
I think it's fine as is. One question to ask yourself: Are each of those methods actually likely to be called?
One option is to just let the programmer set those values after they've instantiated the class:
var myPlayer = new Player();
myPlayer.XP = 5;
However, there are situations where you really want all the info up front, so that may not be suitable.
Another option could be an options class that is passed to the ctor:
public class PlayerSettings
{
public Name = "Player";
public XP = 0;
public LVL = 1;
public XPToLvlUp = 10;
public XpRank = 10;
}
Then your ctors looks like this:
public Player() : this(new PlayerSettings())
{
}
public Player(PlayerSettings settings)
{
//Fill in appropriate variables here
}
That option would be called in this way:
var playerSettings = new PlayerSettings() { XP = 5 };
var myPlayer = new Player(playerSettings());
In the end, I'm not sure one is "better" than the other, it largely depends on your needs.
Your class is almost good and acceptable.
Short story: use Properties.
Long story:
First of all make or follow the naming rules, it will make your code more friendly to read. It's up to you, just a suggestion. For complex names consisting of multiple words you may use CamelCasedNames. And avoid shorten names for all types of data where it maybe useful. For example you may expand Lvl to Level but Xp to Experience will look as something odd. It's up to you too.
string name; // local Variable, first character lower cased
private string _name; // private Field, first character is lower cased with leading "_"
public string Name { get; set; } // public Property, first character is upper cased
I'll show you alternatives to overriden constructors and will follow the naming rules.
1) Default values for constructor (with a part of your class to keep it simple)
class Player
{
public Player(string name = "Player", int xp = 0, int level = 1)
{
Name = name;
Xp = xp;
Level = level;
}
// Properties instead of Fields
public int Xp { get; private set; } // restrict modification of the property outside of a class but reading is available
public int Level { get; private set; }
public string Name { get; set; }
}
2) Properties without constructor with default values
First Property purpose is restrict access to data to keep internal object data consistent. Even you make mistakes in the code. Good way to avoid some bugs.
Second property purpose is executing code while you're getting or setting one. For example, making properties dependent on each other to store less and only unique data.
class Player
{
public int Xp { get; private set; } = 0;
public int Level { get; private set; } = 1;
public string Name { get; set; } = "Player";
}
Usage
Player player = new Player() { Name = "KillerPWNZ", Level = 100, Xp = 999999 };
Bonus: Another Property feature
You can execute any code in get or set clause.
Let's assume that each next player's level require doubled amount of xp from previous but 2nd level requre 100 XP. And you decided to invoice to the 1st leveled player 1000 XP. Obviously you'll need to bump the Level few times. Assuming that Xp contains relative to Level value.
The invoice
player.Xp += 1000;
The Property with code
private int _xp = 0;
public int Level { get; private set; } = 1;
public int Xp
{
get => _xp; // same as: get { return _xp; }
set
{
_xp = value; // here value is keyword containing data you want to set
while (_xp >= GetXpPerLevel(Level))
{
_xp -= GetXpPerLevel(Level);
Level++;
}
while (_xp < 0 && Level > 1)
{
_xp += GetXpPerLevel(Level - 1);
Level--;
}
}
}
// helper method
private int GetXpPerLevel(int level)
{
if (level < 1) return 0;
// int result = 100;
// for (int i = 1; i < level; i++) result *= 2;
// return result;
// or the same with some binary shift magic :)
return 100 << (level - 1);
}

C# Triangle type calculation and area calculation

I am trying to solve or be pointed in the right direction. I am having difficulty determining where to place my Area formula in the Triangle Class (not the main). Area can only have a 'get' and not a 'set'.
Next issue is identifying the type of triangle based on the inputed side and if it is a 'right' triangle, appending the 'type' with '-right' for example (isosceles-right). I have an enum for the triangle types.
I'm not looking for the direct answer to solve this but rather some help and coaching to help better build my skills
Here is the class structure I have generated so far in C#, please keep in mind it is not complete.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TriangleCheck;
namespace TriangleCheck
{
public class Triangle
{
private StringBuilder _ErrorMsg;
private int[] _Sides;
private const int _nSides = 3;
private int _Area;
public Triangle(int[] Sides)
{
//Track amunt of errors recieved.
int nErrors = 0;
//Make sure ErrorMsg is cleared
_ErrorMsg = new StringBuilder();
//Did I get _nSides? If not, append to ErrorMsg and throw exception
if(Sides.Length != _nSides)
{
_ErrorMsg.Append(string.Format("Expected {0} sides but recieved {1}", _nSides, Sides.Length));
nErrors += 1;
}
//Is each side positive? If not, append to ErrorMsg and throw exception
for (int i = 0; i < Sides.Length; i++)
{
if (Sides[i] <= 0)
{
_ErrorMsg.Append(string.Format("{0} side is not a postive integer", Sides[i]));
nErrors += 1;
}
}
//Set input from user to private property _Sides
_Sides = Sides;
_Area = Area;
}
public int Area
{
get { return _Area; }
private set
{
int parameter =
}
}
public string ErrorMsg
{
get
{ return ErrorMsg.ToString();}
}
public bool IsRight
{
get
{
return ;
}
}
public int Sides
{
get
{ return _Sides; }
set
{
if (value > 0)
{
_Sides = value;
}
else
throw new ArgumentOutOfRangeException("Value must be postive!");
}
}
public TriangleTypes TriangleTypes
{
get
{
throw new System.NotImplementedException();
}
set
{
}
}
public void ScaleUp(int[] ScaleFactor)
{
throw new System.NotImplementedException();
}
public override string ToString()
{
return "A Triangle with sides " + _Sides + " is Type: " + TriangleTypes + " with Area:" + Area;
}
}
}
You mention that you can't set the Area property... it looks like you're trying to enforce that by making a private set, but why not just exclude the set leaving it as a read-only property?
The Area formula could go a couple places; the key is that it is derived from the sides but only matters when someone asks for it. So you could reasonably:
Apply the formula and update internal state every time sides changes
Apply the formula and return the value every time someone does a get operation on Area
Remember the point of getter and setter being functions is that they could contain logic to execute (to fully update internal state in setter, or to calculate the value of a read-only derived property).
More sophisticated patterns exist if performance of the area calculation were very worrisome, but I wouldn't get into that at this point.
As for determining if the triangle is right... if it is, which side must be the hypotenuse? What relationship do you know between the length of the hypotenuse and the lengths of the other sides, if the triangle is right?
using System;
namespace ConsoleApp
{
class Program
{
static void Main()
{
var t = new Triangle(2, 3, 5);
//var Triangle = new Triangle(2); // won't compile as no Triangle constructor can be found that takes 1 integer
//var Triangle = new Triangle(2, 3, 5, 7); // won't compile as no Triangle constructor can be found that takes 4 integers
//var Triangle = new Triangle(2, -3, 5); // won't compile as the 2nd value is negative - and we've asked for unsigned for all 3 values
Console.WriteLine("The triangle ({0}, {1}, {2}) has an area of {3}.", t.A, t.B, t.C, t.area());
Console.ReadKey();
}
}
public class Triangle
{
public uint A { get; set; }
public uint B { get; set; }
public uint C { get; set; }
public Triangle(uint a, uint b, uint c)
{
this.A = a;
this.B = b;
this.C = c;
}
public uint area()
{
return A * B * C; // this needs fixing ...
}
}
}
Isn't this roughly what you are trying to achieve with your Triangle class - a way of stopping it being used incorrectly with too few or incorrect types of arguments. This one only allows 3 positive (uint) integers. Nothing else will comple - which is what you want. Sorry if I have misunderstood.

Linq performance: should I first use `where` or `select`

I have a large List in memory, from a class that has about 20 properties.
I'd like to filter this list based on just one property, for a particular task I only need a list of that property. So my query is something like:
data.Select(x => x.field).Where(x => x == "desired value").ToList()
Which one gives me a better performance, using Select first, or using Where?
data.Where(x => x.field == "desired value").Select(x => x.field).ToList()
Please let me know if this is related to the data type I'm keeping the data in memory, or field's type. Please note that I need these objects for other tasks too, so I can't filter them in the first place and before loading them into memory.
Which one gives me a better performance, using Select first, or using Where.
Where first approach is more performant, since it filters your collection first, and then executes Select for filtered values only.
Mathematically speaking, Where-first approach takes N + N' operations, where N' is the number of collection items which fall under your Where condition.
So, it takes N + 0 = N operations at minimum (if no items pass this Where condition) and N + N = 2 * N operations at maximum (if all items pass the condition).
At the same time, Select first approach will always take exactly 2 * N operations, since it iterates through all objects to acquire the property, and then iterates through all objects to filter them.
Benchmark proof
I have completed the benchmark to prove my answer.
Results:
Condition value: 50
Where -> Select: 88 ms, 10500319 hits
Select -> Where: 137 ms, 20000000 hits
Condition value: 500
Where -> Select: 187 ms, 14999212 hits
Select -> Where: 238 ms, 20000000 hits
Condition value: 950
Where -> Select: 186 ms, 19500126 hits
Select -> Where: 402 ms, 20000000 hits
If you run the benchmark many times, then you will see that Where -> Select approach hits change from time to time, while Select -> Where approach always takes 2N operations.
IDEOne demonstration:
https://ideone.com/jwZJLt
Code:
class Point
{
public int X { get; set; }
public int Y { get; set; }
}
class Program
{
static void Main()
{
var random = new Random();
List<Point> points = Enumerable.Range(0, 10000000).Select(x => new Point { X = random.Next(1000), Y = random.Next(1000) }).ToList();
int conditionValue = 250;
Console.WriteLine($"Condition value: {conditionValue}");
Stopwatch sw = new Stopwatch();
sw.Start();
int hitCount1 = 0;
var points1 = points.Where(x =>
{
hitCount1++;
return x.X < conditionValue;
}).Select(x =>
{
hitCount1++;
return x.Y;
}).ToArray();
sw.Stop();
Console.WriteLine($"Where -> Select: {sw.ElapsedMilliseconds} ms, {hitCount1} hits");
sw.Restart();
int hitCount2 = 0;
var points2 = points.Select(x =>
{
hitCount2++;
return x.Y;
}).Where(x =>
{
hitCount2++;
return x < conditionValue;
}).ToArray();
sw.Stop();
Console.WriteLine($"Select -> Where: {sw.ElapsedMilliseconds} ms, {hitCount2} hits");
Console.ReadLine();
}
}
Related questions
These questions can also be interesting to you. They are not related to Select and Where, but they are about LINQ order performance:
Does the order of LINQ functions matter?
Order of LINQ extension methods does not affect performance?
The answer will depend on the state of your collection.
If most entities will pass the Where test, apply Select first;
If fewer entities will pass the Where test, apply Where first.
Update:
#YeldarKurmangaliyev wrote the answer with a concrete example and benchmarking. I ran similar code to verify his claim and our results are exactly opposite and that is because I ran the same test as his but with an object not as simple as the Point type he used to run his tests.
The code very much looks like his code, except that I changed the name of class from Point to EnumerableClass.
Given below the classes I used to constitute the EnumerableClass class:
public class EnumerableClass
{
public int X { get; set; }
public int Y { get; set; }
public String A { get; set; }
public String B { get; set; }
public String C { get; set; }
public String D { get; set; }
public String E { get; set; }
public Frame F { get; set; }
public Gatorade Gatorade { get; set; }
public Home Home { get; set; }
}
public class Home
{
private Home(int rooms, double bathrooms, Stove stove, InternetConnection internetConnection)
{
Rooms = rooms;
Bathrooms = (decimal) bathrooms;
StoveType = stove;
Internet = internetConnection;
}
public int Rooms { get; set; }
public decimal Bathrooms { get; set; }
public Stove StoveType { get; set; }
public InternetConnection Internet { get; set; }
public static Home GetUnitOfHome()
{
return new Home(5, 2.5, Stove.Gas, InternetConnection.Att);
}
}
public enum InternetConnection
{
Comcast = 0,
Verizon = 1,
Att = 2,
Google = 3
}
public enum Stove
{
Gas = 0,
Electric = 1,
Induction = 2
}
public class Gatorade
{
private Gatorade(int volume, Color liquidColor, int bottleSize)
{
Volume = volume;
LiquidColor = liquidColor;
BottleSize = bottleSize;
}
public int Volume { get; set; }
public Color LiquidColor { get; set; }
public int BottleSize { get; set; }
public static Gatorade GetGatoradeBottle()
{
return new Gatorade(100, Color.Orange, 150);
}
}
public class Frame
{
public int X { get; set; }
public int Y { get; set; }
private Frame(int x, int y)
{
X = x;
Y = y;
}
public static Frame GetFrame()
{
return new Frame(5, 10);
}
}
The classes Frame, Gatorade and Home have a static method each to return an instance of their type.
Below is the main program:
public static class Program
{
const string Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static readonly Random Random = new Random();
private static string RandomString(int length)
{
return new string(Enumerable.Repeat(Chars, length)
.Select(s => s[Random.Next(s.Length)]).ToArray());
}
private static void Main()
{
var random = new Random();
var largeCollection =
Enumerable.Range(0, 1000000)
.Select(
x =>
new EnumerableClass
{
A = RandomString(500),
B = RandomString(1000),
C = RandomString(100),
D = RandomString(256),
E = RandomString(1024),
F = Frame.GetFrame(),
Gatorade = Gatorade.GetGatoradeBottle(),
Home = Home.GetUnitOfHome(),
X = random.Next(1000),
Y = random.Next(1000)
})
.ToList();
const int conditionValue = 250;
Console.WriteLine(#"Condition value: {0}", conditionValue);
var sw = new Stopwatch();
sw.Start();
var firstWhere = largeCollection
.Where(x => x.Y < conditionValue)
.Select(x => x.Y)
.ToArray();
sw.Stop();
Console.WriteLine(#"Where -> Select: {0} ms", sw.ElapsedMilliseconds);
sw.Restart();
var firstSelect = largeCollection
.Select(x => x.Y)
.Where(y => y < conditionValue)
.ToArray();
sw.Stop();
Console.WriteLine(#"Select -> Where: {0} ms", sw.ElapsedMilliseconds);
Console.ReadLine();
Console.WriteLine();
Console.WriteLine(#"First Where's first item: {0}", firstWhere.FirstOrDefault());
Console.WriteLine(#"First Select's first item: {0}", firstSelect.FirstOrDefault());
Console.WriteLine();
Console.ReadLine();
}
}
Results:
I ran the tests multiple times and found that
.Select().Where() performed better than .Where().Select().
when collection size is 1000000.
Here is the first test result where I forced every EnumerableClass object's Y value to be 5, so every item passed Where:
Condition value: 250
Where -> Select: 149 ms
Select -> Where: 115 ms
First Where's first item: 5
First Select's first item: 5
Here is the second test result where I forced every EnumerableClass object's Y value to be 251, so no item passed Where:
Condition value: 250
Where -> Select: 110 ms
Select -> Where: 100 ms
First Where's first item: 0
First Select's first item: 0
Clearly, the result is so dependent on the state of the collection that:
In #YeldarKurmangaliyev's tests .Where().Select() performed better; and,
In my tests .Select().Where() performed better.
The state of the collection, which I am mentioning over and over includes:
the size of each item;
the total number of items in the collection; and,
the number of items likely to pass the Where clause.
Response to comments on the answer:
Further, #Enigmativity said that knowing ahead of time the result of Where in order to know whether to put Where first or Select first is a Catch-22. Ideally and theoretically, he is correct and not surprisingly, this situation is seen in another domain of Computer Science - Scheduling.
The best scheduling algorithm is Shortest Job First where we schedule that job first that will execute for the least time. But, how would anyone know how much time will a particular job take to complete? Well, the answer is that:
Shortest job next is used in specialized environments where accurate estimates of running time are available.
Therefore, as I said right at the top (which was also the first, shorter version of my answer), the correct answer to this question will depend on the current state of the collection.
In general,
if your objects are within a reasonable size range; and,
you are Selecting a very small chunk out of each object; and,
your collection size is also not just in thousands,
then the guideline mentioned right at the top of this answer will be useful for you.

Property by ref C# (many parameters)

chaps/chapettes, I understand there are questions related to this but this is somewhat different - all related questions I could find only used one parameter as an example. Anyways, to the point:
This year, I have converted source code written in Delphi to C#. Beyond this, the scope of my tasks has been to optimize and generally improve the code base. The source code has been written by a handful of individuals, each with no knowledge or experience of software engineering principles or techniques - so some of the code is abismal.
Anyhow, perhaps someone can provide a suggestion/solution to my quarrels:
Currently, in C# have a class for storing 9 values:
class StoreStruct
{
int A1 { get; set;}
int B1 { get; set;}
int C1 { get; set;}
int A2 { get; set;}
int B2 { get; set;}
int C2 { get; set;}
int A3 { get; set;}
int B3 { get; set;}
int C3 { get; set;}
}
Now what I have an issue with is that, ideally, I would like to pass the properties of this class into methods by ref. However, I know I can't do this. Instead the source code works by creating temp local variables, passes these by ref and then assigns the class properties to these values. This can be seen as follows:
private void MethodA()
{
var temp = new StoreStruct();
var a1 = 0;
var b1 = 0;
var c1 = 0;
var a2 = 0;
var b2 = 0;
var c2 = 0;
var a3 = 0;
var b3 = 0;
var c3 = 0;
if (expression1)
{
MethodB(ref a1, ref b1, ref c1, 1, 1);
temp.A1 = a1;
temp.B1 = b1;
temp.C1 = c1;
}
if (expression2)
{
MethodB(ref a2, ref b2, ref c2, 2, 2);
temp.A2 = a2;
temp.B2 = b2;
temp.C2 = c2;
}
if (expression3)
{
MethodB(ref a3, ref b3, ref c3, 3, 3);
temp.A3 = a3;
temp.B3 = b3;
temp.C3 = c3;
}
}
private void MethodB(ref int a, ref int b, ref int c, int num1, int num2)
{
a = num1 + num2;
b = num1 - num2;
c = num1 * num2;
}
What I would like to do in an ideal world:
MethodB(ref temp.A1, ref temp.B1, ref temp.C1, 1, 1);
From looking at other posts, I understand why this isn't catered for in C# and quite frankly I agree with the reasoning behind it. I have seen a few workarounds and a few suggestions in other posts but these only relate to an example with one method call and only one parameter being passed by ref. Does anyone have an elegant solution that would allow me to update the class properties in MethodB without having to pass temporary variables?
Just remove getters and setters from StoreStruct.
Personally I would use the workaround you did in your question. However if you really want it you would need to pass delegates in to the function that would assign the values for you then call them inside your function.
if (expression1)
{
MethodB((a) => temp1.A1 = a,
(b) => temp1.B1 = b,
(c) => temp1.C1 = c,
1, 1);
}
private void MethodB(Func<int> setA,
Func<int> setB,
Func<int> setC,
int num1, int num2)
{
setA(num1 + num2);
setB(num1 - num2);
setC(num1 * num2);
}
Properties are nothing but syntactic sugar for getter and setter function calls, which is why you cannot pass them by reference. In general in C# if you're using ref parameters, you're probably doing it wrong.
Simply pass the StoreStruct object, and let the function set the properties. A class is a reference type, so essentially all objects are passed "by reference" by default in C#.
I think modifying your StoreStruct will help with this, and eliminate a bunch of madness:
class Thing {
int A { get; set; }
int B { get; set; }
int C { get; set; }
}
class StoreStruct { // Not actually a struct!
public readonly Thing thing1;
public readonly Thing thing2;
public readonly Thing thing3;
}
Use:
private void MethodA()
{
var temp = new StoreStruct();
if (expression1)
{
MethodB(temp.thing1, 1, 1);
}
if (expression2)
{
MethodB(temp.thing2, 1, 1);
}
if (expression3)
{
MethodB(temp.thing3, 1, 1);
}
}
private void MethodB(Thing thing, int num1, int num2)
{
thing.A = num1 + num2;
thing.B = num1 - num2;
thing.C = num1 * num2;
}
Well, if it were me the first thing I'd do is try to get some real names here. What's an A1, B2, etc? Is it a cash register? A puppy? A space sled? Names should reflect what's going on. Next, ideally classes should modify their own data as much as possible, so I would tend to think in terms of passing the object and calling as few methods as possible on the object to do whatever modifications are needed rather than passing around a set of flags, especially if the latter have really obtuse names. Sorry if that seems like more of a general criticism, but it goes to what you mentioned about being tasked to improve the code base over time. (If they're really structs, I've always found properties to be overkill except insofar as they might aid debugging).
It seems that you are having three sets of values in your class. If you make a class of such a set, you can have three values in the class:
class ABC {
int A { get; set; }
int B { get; set; }
int C { get; set; }
}
class StoreStruct {
ABC ABC1 { get; set; }
ABC ABC2 { get; set; }
ABC ABC3 { get; set; }
public StoreStruct {
ABC1 = new ABC();
ABC2 = new ABC();
ABC3 = new ABC();
}
}
Now you can pass an ABC value into MethodB, and as that is a changeable set of values, you don't even need the ref keyword for the parameter:
private void MethodB(ABC abc, int num1, int num2) {
abc.A = num1 + num2;
abc.B = num1 - num2;
abc.C = num1 * num2;
}
Call:
MethodB(temp.ABC1, 1, 1);
You could also make MethodB a member of the class ABC, so that you don't pass the value to the method, you call the method on the value:
class ABC {
int A { get; set; }
int B { get; set; }
int C { get; set; }
public void MethodB(int num1, int num2) {
A = num1 + num2;
B = num1 - num2;
C = num1 * num2;
}
}
Usage:
temp.ABC1.MethodB(1, 1);
I agree with Jonathan's comment that you're probably doing something wrong and could encapsulate your state in a way that doesn't require passing by ref.
In order to do what you want, you can use a backing variable for the getters/setters.
private int _a1;
public int A1
{
get
{
return _a1;
}
set
{
_a1 = value;
}
}
public void Foo()
{
Bar(ref _a1);
}
It looks like you want to exchange every Property of a class. In the OOP-world the best way to do this is to send the complete class to the method, not just the properties:
public void MethodB(ref StoreStruct store) {
// store.A1=[...];
}
Wow, lots of answers to this question already. Well, here's another. You could try creating a class that can act as a reference to an integer like this:
class IntRef
{
private int value;
public IntRef(int value)
{
this.value = value;
}
public static implicit operator IntRef(int value)
{
return new IntRef(value);
}
public static implicit operator int(IntRef value)
{
return value.value;
}
}
Then change your int declarations and your ref int paremeters to IntRef.
Be aware that if you do this, though, that your set procedure may not run. You may have to move some of that code into the IntRef class or raise an event from IntRef so that the StoreStruct can react to the changed value.

A custom datetime struct

I am trying to develop a clock application with images for each digits from 0-9. Wrote a struct that gives me each digits every now and then. Following is the struct.
public struct TimeStruct
{
public DateTime dt
{
get
{
return DateTime.Now;
}
}
public int s
{
get
{
return dt.Second;
}
}
public int s2
{
get
{
return s % 10;
}
}
public int s1
{
get
{
return s / 10;
}
}
public int m
{
get
{
return dt.Minute;
}
}
public int m2
{
get
{
return m % 10;
}
}
public int m1
{
get
{
return m / 10;
}
}
public int h
{
get
{
return dt.Hour;
}
}
public int h2
{
get
{
return h % 10;
}
}
public int h1
{
get
{
return h / 10;
}
}
public int d
{
get
{
return (int)dt.DayOfWeek;
}
}
}
Please guide me to modify this struct so that the prop s2 should be set only when s1 becomes 0. And the same with minutes.
Technology Used : Silverlight
Platform : Windows Phone 7
Was that a bad idea to use struct?
What do you mean by "prop s2 should be set only when s1 becomes 0" - what do you want it to do when s1 isn't 0? Are you perhaps looking for nullable value types, where s1 would return the null value in some cases?
I have to say, I think this is a pretty confusing type. It has no real state - it's effectively just a bunch of static properties. Any reason for not implementing it as a bunch of static properties, e.g. in a CurrentDateTime class? Or just use DateTime.Now? Note that if you ask your struct for a bunch of values, one at a time, it may very well give you inconsistent results as time will pass. For example, suppose the time is 1:59:59 and you call s, then m, then h - you may end up getting 59, 59, 2 as the current time rolls over from 1:59:59 to 2:00:00 between the last two calls. If you take the value of DateTime.Now just once and ask it for all its properties, you'll get a consistent view.
Why re-invent the wheel ? Use DateTime and TimeSpan.

Categories