C# interchangeable properties - c#

I'm trying to create a substitute for kind of property, that accepts multiple types as inputs/outputs.
Here is some pseudo code of one ugly solution:
http://pastebin.com/gbh4SrZX
Basically i have piece of data and i need to be able assign multiple types to it, and react accordingly. I have pieces of data that i operate with, and i need efficient way to manage loading them from file names when needed, while maintaining the same code, if I'm manipulating with data, that's already loaded.
This would be awesome:
SomeDataClass data1 = new SomeDataClass();
SomeDataClass data2 = new SomeDataClass();
data1.Data = "somefile.dat";
data2.Data = data1.Data;
while SomeDataClass.Data is not type of string.

Have you considered using dynamic?
class A {
public dynamic property1 { get; set; }
public dynamic property2 { get; set; }
}
class Program {
static void Main(string[] args) {
A a = new A();
A b = new A();
a.property1 = "hello world!";
b.property2 = a.property1;
Console.WriteLine(b.property2); // writes "hello world!"
}
}

You can do much of that with an implicit conversion operator, i.e.
class SomeDataClass {
public SomeData Data {get;set;}
}
class SomeData {
static SomeData Load(string path) {
return new SomeData(); // TODO
}
public static implicit operator SomeData(string path)
{
return Load(path);
}
}
static class Program {
static void Main()
{
SomeDataClass data1 = new SomeDataClass();
SomeDataClass data2 = new SomeDataClass();
data1.Data = "somefile.dat"; // this is a load
data2.Data = data1.Data; // this is not a load
}
}
However! Frankly, I would consider it more desirable to just make the operation explicit:
class SomeDataClass {
public SomeData Data {get;set;}
}
class SomeData {
public static SomeData Load(string path) {
return new SomeData(); // TODO
}
}
static class Program {
static void Main()
{
SomeDataClass data1 = new SomeDataClass();
SomeDataClass data2 = new SomeDataClass();
data1.Data = SomeData.Load("somefile.dat");
data2.Data = data1.Data;
}
}

Not sure what the problem you're trying to solve with this really is, but it seems to me like you'd be better of with using a byte[], working with a stream of data, loaded either from disk or somewhere else.
Also consider just coding to a common Interface, instead of using dynamic and object.

Related

Set returned value from method as public string in C#

I need to get string from one class to another class,
It is possible to set public string from method I mean like in this code:
class test
{
static void Main(string[] args)
{
load();
}
public class Data
{
public string datacollected { get; set; }
}
public static void load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
Data datacfg = new Data();
var datanew = System.Text.Json.JsonSerializer.Deserialize<List<Data>>(jsonString);
datacfg = datanew.First();
}
public string datacollected = datacfg.datacollected;
}
i want to use string datacollected in another class and in another public void
The datacollected member that is directly in the test class is not a property. It's a field. Fields that have an assignment on the same statement as the declaration are evaluated before* the class's constructor (ie: before the Main method runs).
You probably want it to be a property instead, which is evaluated each time you access the member. The simplest method to fix that is by adding a > after the equals.
public string datacollected => datacfg.datacollected;
You've got two other problems though.
datacollected (in the test class) isn't static. All of your methods are static, and therefor wouldn't be able to access the non-static member.
You've still got the problem where the datacfg is a local variable that is defined inside the load method. You can't use variables outside their defined scope.
Option 1: you only need the parsed file data in the method that called load.
Change load to return the parsed data, rather than save it to a class-global variable.
using System.Text.Json;
static class test
{
static void Main(string[] args)
{
Data loadedData = load();
}
public static Data load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
return JsonSerializer.Deserialize<List<Data>>(jsonString).First();
}
}
public class Data
{
public string datacollected { get; set; }
}
Option 2: If you really need some global variable, put the whole Data object up to a field instead. This doesn't use a property - there's really no advantage in this case.
using System.Text.Json;
static class test
{
// assuming you're using nullable reference types (the "?")
private static Data? loadedData;
static void Main(string[] args)
{
load();
Console.WriteLine(loadedData!.datacollected);
// "!" to tell compiler that you know loadedData
// shouldn't be null when executed
}
public static void load()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
loadedData = JsonSerializer.Deserialize<List<Data>>(jsonString).First();
}
}
public class Data
{
public string datacollected { get; set; }
}
I'd go with Option 1 if at all possible.
* I don't remember if it's before, during, or after.
You can declare a class like this
public class UseData
{
private List<Data> _data=null;
public string datacollected
{
get
{
if (_data == null)
LoadData();
return _data.First().datacollected;
}
}
private void LoadData()
{
string fileName = "samplefile.json";
string jsonString = File.ReadAllText(fileName);
_data = System.Text.Json.JsonSerializer.Deserialize<List<Data>>(jsonString);
}
}
which have a private list of data and it loads from your json file at first time you called. Next time you call it, as the private _data object is filled, it wont load again and the datacollected property returns the first data object's datacollected string property.

List of distinct types without casting to common superclass

How do I store objects in a list, but have them retain their original type? Without being casted to their common superclass.
So that the below code can work:
using System;
using System.Collections.Generic;
public class Test
{
public static void Main(string[] args)
{
var list = new List<Super>()
{
new Type1 { Number = 1, Info = "infomatin" },
new Type2 { Number = 2, Prop = "propty" }
};
foreach (var t in list)
{
Doer.Do(t);
}
}
}
public class Super
{
public int Number { get; set; }
}
public class Type1 : Super
{
public string Info { get; set; }
}
public class Type2 : Super
{
public string Prop { get; set; }
}
public static class Doer
{
public static void Do(Type1 arg)
{
Console.WriteLine($"Got type 1 with {arg.Info}");
}
public static void Do(Type2 arg)
{
Console.WriteLine($"Got type 2 with {arg.Prop}");
}
}
Wanted output:
Got type 1 with infomatin
Got type 2 with propty
Actual output, compiler error:
Test.cs(15,21): error CS1503: Argument 1: cannot convert from 'Super' to 'Type1'
I could do this inside the foreach
if (t instanceof Type1)
Doer.Do((Type1) t);
else if (t instanceof Type2)
Doer.Do((Type2) t);
But I don't want to have to write so much code. Especially as I add more subclasses of Super.
I would like to have to add only an additional method to my Doer to handle the new type, then the rest is taken care of.
You can use pattern matching, with only one Do() method
public static void Do(Super arg)
{
switch(arg)
{
case Type1 t1:
Console.WriteLine($"Got type 1 with {t1.Info}");
break;
case Type2 t2:
Console.WriteLine($"Got type 2 with {t2.Prop}");
break;
default:
throw new NotSupportedException();
}
}
As far as avoiding casting, I feel you have misunderstood how C# works. When you store in a base class, the memory contents are still the of the derived class and there is not casting in the sense of copying data from one type to another
This type of operation does not involve any data copy
Super obj = new Type1();
Neither does this
Type1 t1 = (Type1)obj;
It just the reference t1 putting on a different "mask" than obj, and the data behind the mask is the same.
Edit 1
A any casting (of the form (type)value in C#) is cast that might include a conversion or not. Some examples where obj is if type object, sup is of type class Super, t1 is of type class Type1 : Super and t2 is of type class Type2 : Super.
No conversion, or identity casts
obj = sup;
sup = t1;
sup = t2;
sup = t1; t1 = (Type1)sup;
obj = t1; sup = (Super)obj;
obj = t1; sup = (Type1)t1;
The code below requires the following custom conversion code to be added to Type1 and Type2 respectively.
public static implicit operator Type1(Type2 t2) => new Type1() { Info = t2.Prop };
public static explicit operator Type2(Type1 t1) => t1.Info.StartsWith("prop") ? new Type2() { Prop = t1.Info } : throw new NotSupportedExpection();
Implicit Conversion casts (data copy, may fail)
{ // Implicit conversion Type2 -> Type1
object obj = new Type2() { ID = 2, Prop = "propval" };
Type1 t1 = (Type2)obj;
}
Explicit Conversion casts (data copy, may fail)
{
// Explicit conversion Type1 -> Type2
object obj = new Type1() { ID = 1, Info = "propInfo" };
Type2 t2 = (Type2)(Type1)obj;
}
Read https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions. for more accurate information.
If you find yourself using switch/case and casting, there's a good chance you're doing it wrong. With a properly designed object model, it shouldn't be necessary.
For example
abstract public class Super
{
public int Number { get; set; }
public abstract void Do();
}
public class Type1 : Super
{
public string Info { get; set; }
public override void Do()
{
Console.WriteLine($"Got type 1 with {this.Info}");
}
}
public class Type2 : Super
{
public string Prop { get; set; }
public override void Do()
{
Console.WriteLine($"Got type 2 with {this.Prop}");
}
}
Now you can just do this in your loop:
public static void Main(string[] args)
{
var list = new List<Super>()
{
new Type1 { Number = 1, Info = "infomatin" },
new Type2 { Number = 2, Prop = "propty" }
};
foreach (var t in list)
{
t.Do();
}
}
The above is consistent with Tell, Don't Ask which is a traditional object-oriented philosophy.
If you are worried about separation of concerns (for example, you don't want your classes to have knowledge of "Console") then you can inject the external functionality:
abstract public class Super
{
public int Number { get; set; }
public abstract void Do(Action<int> action);
}
public class Type1 : Super
{
public string Info { get; set; }
public override void Do(Action<int> action)
{
action(this.Info);
}
}
public class Type2 : Super
{
public string Prop { get; set; }
public override void Do(Action<int> action)
{
action(this.Prop);
}
}
public static void Main(string[] args)
{
var list = new List<Super>()
{
new Type1 { Number = 1, Info = "infomatin" },
new Type2 { Number = 2, Prop = "propty" }
};
foreach (var t in list)
{
t.Do( x => Console.WriteLine("The value that we're interested in is {0}", x));
}
}
There is one more situation which may apply here (based on your comments). Let's say you have "clean" DTO objects that have no methods, and you don't want to add any for whatever reason, e.g. maybe the DTOs are code-generated and you can't modify them. This is actually a common situation (I like methodless DTOs too).
To make the situation more real, let's use more meaningful examples. Let's say you have a variety of objects that might contain an end user's name, but with various different identifiers:
abstract public class Super
{
}
public class Type1 : Super
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Type2 : Super
{
public string FullName { get; set; }
}
The temptation here is to write a switch case like this:
foreach (var t in list)
{
switch (t)
{
case Type1 type1 : Console.WriteLine("Name is {0} {1}", type1.FirstName, type1.LastName);
case Type2 type2: Console.WriteLine("Name is {0}", type2.FullName);
default:
throw new InvalidOperationException();
}
}
The problem here is that runtime throw, which will occur any time someone adds a different object type but doesn't remember to update your switch statement. This might not be a problem, but it also might be a huge problem, e.g. if your DTOs are held in a separate library from your Do processor and you would rather not have to update both at the same time (which could be a deployment concern under certain architectures).
What is missing here is a business concept of "Name" agnostic of where it came from. Somewhere, some code has to translate these various objects into something that has a name, and preferably that logic would be encapsulated somewhere.
That's where I would use an adapter class.
class NameHolder
{
public string FullName { get; }
public NameHolder(Type1 type1)
{
this.FullName = type1.FirstName + " " + type1.LastName;
}
public NameHolder(Type2 type2)
{
this.FullName = type2.FullName;
}
}
With the addition of this missing business concept, the logic become very simple:
public static void Main(string[] args)
{
var list = new List<NameHolder>()
{
new NameHolder(new Type1 { Number = 1, Info = "infomatin" }),
new NameHolder(new Type2 { Number = 2, Prop = "propty" })
};
foreach (var t in list)
{
Do(t.FullName);
}
}
Notice the lack of throw. The advantage of this approach is that all types are resolved at compile time, so if you forget to add logic to map the proper fields, you will get a compile time error, which you can detect and fix immediately.

Error on static Class

public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.

performing a child classes method when called as a parent

I have a class Class A, and a class Class B.
class B is a child of class A so that:
public class Class A
{
public DateTime FileStart
{
get
{
return Header.StartTime;
}
set{ }
}
...
...
}
and
public class B : A
{
FileInfo zippedA;
public A myA = null;
internal B(FileInfo mFileInfo)
{
...
//collects the same data as A from the fileinfo such as start time...
...
}
public A getAData()
{
UnZipFile(zippedA);
return myA;
}
...
}
So I'm looking for a way to call getAData() whenever an object of B is called as A for example the list Xlist stores all As and Bs but will be accessed from several places in the code:
SortedList Xlist = new SortedList();
public void GetFrames(DateTime desiredStartTime, DateTime desiredEndTime)
{
for(int fileIdx = Xlist.Values.Count-1; fileIdx >= 0; --fileIdx)
{
//my hope is that there is a way to set up B in it's class to say
// "if I get called as an A, I'll perform getAData() and return myA instead.
A rec = (A)Xlist.GetByIndex(fileIdx);
...
...
}
}
in the above instance I would like for every time an object is pulled from Xlist if its a B but gets caste as an A like so, it automatically calls the getAData() function and returns the resulting A instead of its self. is this possible??
You can make the method in parent class virtual and override it in the child classes. In doing so anywhere you call the method on an instance of type A, it will invoke the method in the derived type if the derived type provides and override, otherwise it will invoke the version in type A.
This is the simplest way, the alternative aren't very attractive. For more information on virtual methods in C# check out this msdn article; http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx
To do what you think you want to do (I'm pretty sure it's not actually what you want to do) you can do this;
for(int fileIdx = Xlist.Values.Count-1; fileIdx >= 0; --fileIdx)
{
A rec = (A)Xlist.GetByIndex(fileIdx);
if (rec.GetType() == typeof(B))
{
B temp = (B) rec;
rec = temp.getAData();
}
}
Although, again, this makes no sense at all. Here's an example;
public class Car
{
int year;
bool manual;
}
public class Porsche : Car
{
bool specialPorscheOnlyFeature;
Engine enginge;
}
public class Engine
{
string engineType;
}
// in some method
Porsche p = new Porsche();
// to get Car data
int yearOfCar = p.year;
bool isManual = p.manual;
bool specialFeature = p.SpecialPorscheOnlyFeature;
Above is an example of how inheritance works. I don't retrieve an instance of the base class, everything the base class has is baked into the instance of the derived class. You're acting like the base class is some other object the derived class is composed of.
It may not be the best way to do it, but would this not work?
class File
{
public string FileInfo = "";
public override string ToString()
{
return FileInfo;
}
public virtual File GetRaw()
{
return this;
}
}
class ZippedFile : File
{
public File Unzip()
{
// Do actual unzip here..
return new File { FileInfo = FileInfo.Substring(0,8) };
}
public override File GetRaw()
{
return Unzip();
}
}
class Program
{
static void Main(string[] args)
{
List<object> files = new List<object>();
files.Add(new File { FileInfo = "BeepBoop" });
files.Add(new ZippedFile { FileInfo = "BeepBoopfQAWEFRLQER:LKAR:LWEasdfw;lekfrqW:ELR" });
files.Add(new File { FileInfo = "BoopBeep" });
files.Add(new ZippedFile { FileInfo = "BoopBeepAWSLF:KQWE:LRKsdf;lKWEFL:KQwefkla;sdfkqwe" });
foreach(var f in files)
{
File rawFile = ((File)f).GetRaw();
Console.WriteLine(rawFile);
}
Console.ReadKey();
}
}

Arguments on properties

Assuming there's an enumeration defined as follows:
public enum Beep
{
HeyHo,
LetsGo
}
I wonder if it's possible to improve the following property:
public Dictionary<Beep, String> Stuff{ get; set; }
...
String content = Stuff[Beep.HeyHo]
because the way it's right now, I retrieve the dictionary and then pick out the element I need. I wonder if it's (a) possible at all and if so (b) recommended to create something like this pseudo-code.
public String Stuff{ get<Beep>; set<Beep>; }
...
String content = Stuff[Beep.HeyHo]
You can apply an indexer to your class.
It is recommended, as it improves encapsulation. For example, it's perfectly possible using the original code to replace the Dictionary entirely with a different dictionary - which is probable not desirable.
public class MyClass
{
// Note that dictionary is now private.
private Dictionary<Beep, String> Stuff { get; set; }
public String this[Beep beep]
{
get
{
// This indexer is very simple, and just returns or sets
// the corresponding element from the internal dictionary.
return this.Stuff[beep];
}
set
{
this.Stuff[beep] = value;
}
}
// Note that you might want Add and Remove methods as well - depends on
// how you want to use the class. Will client-code add and remove elements,
// or will they be, e.g., pulled from a database?
}
Usage:
MyClass myClass = new MyClass();
string myValue = myClass[Beep.LetsGo];
You can also use an indexer.
class MyClass
{
private readonly Dictionary<Beep, string> _stuff = new Dictionary<Beep, string>();
public string this[Beep beep]
{
get { return _stuff[beep]; }
set { _stuff[beep] = value; }
}
}
Now, instead of calling
var obj = new MyClass();
string result = obj.Stuff[Beep.HeyHo];
You can call
var obj = new MyClass();
string result = obj[Beep.HeyHo];
Indexers work much like properties but have at least one argument used as index. You can have only one indexer per class, however you can create different overloads of it. The same overloading rules apply as for methods.
Something like this using Indexer
public class Stuff
{
public Dictionary<Beep, String> _stuff { get; set; }
public enum Beep
{
HeyHo,
LetsGo
}
public Stuff()
{
_stuff = new Dictionary<Beep, string>();
// add item
_stuff[Beep.HeyHo] = "response 1";
_stuff[Beep.LetsGo] = "response 2";
}
public string this[Beep beep]
{
get { return _stuff[beep]; }
}
}
Sample Usage :
public static class Program
{
private static void Main()
{
Stuff stuff = new Stuff();
string response;
response = stuff[Stuff.Beep.HeyHo]; // response 1
response = stuff[Stuff.Beep.LetsGo]; // response 2
}
}

Categories

Resources