C#4.0 brings optional parameters, which I've been waiting for for quite some time. However it seems that because only System types can be const, I cannot use any class/struct which I have created as an optional parameter.
Is there a some way which allows me to use a more complex type as an optional parameter. Or is this one of the realities that one must just live with?
The best I could come up with for reference types was:
using System;
public class Gizmo
{
public int Foo { set; get; }
public double Bar { set; get; }
public Gizmo(int f, double b)
{
Foo = f;
Bar = b;
}
}
class Demo
{
static void ShowGizmo(Gizmo g = null)
{
Gizmo gg = g ?? new Gizmo(12, 34.56);
Console.WriteLine("Gizmo: Foo = {0}; Bar = {1}", gg.Foo, gg.Bar);
}
public static void Main()
{
ShowGizmo();
ShowGizmo(new Gizmo(7, 8.90));
}
}
You can use the same idea for structs by making the parameter nullable:
public struct Whatsit
{
public int Foo { set; get; }
public double Bar { set; get; }
public Whatsit(int f, double b) : this()
{
Foo = f; Bar = b;
}
}
static void ShowWhatsit(Whatsit? s = null)
{
Whatsit ss = s ?? new Whatsit(1, 2.3);
Console.WriteLine("Whatsit: Foo = {0}; Bar = {1}",
ss.Foo, ss.Bar);
}
You can use any type as an optional parameter:
using System;
class Bar { }
class Program
{
static void Main()
{
foo();
}
static void foo(Bar bar = null) { }
}
Okay, I reread your question and I think I see what you mean - you want to be able to do something like this:
static void foo(Bar bar = new Bar()) { }
Unfortunately this is a not allowed since the value of the default parameter must be known at compile time so that the compiler can bake it into the assembly.
Related
I am creating a program in C# and I don't know how to create my classes.
Here's what my class looks like:
public class MyClass
{
public class Parameters
{
string Value { get; set;}
}
public class Methods
{
public void MyMethod()
{
Window.Title = Parameters.Value;
}
}
}
And this is how I want to be able to use it from another class:
public class MainClass
{
MyClass myclass = new MyClass();
myclass.Parameters.Value = "Hello World !";
myclass.Methods.MyMethod();
System.Threading.Thread.Sleep(Timespan.FromSeconds(10));
MyClass myclass2 = new MyClass();
myclass2.Parameters.Value = "Hello World Again !";
myclass2.Methods.MyMethod();
//I know this code is stupid, it's just to simplify my example.
}
But it doesn't work, there are accessibility problems that I don't know how to solve.
Thanks in advance, I don't think that the solution is very complicated but I can't find it.
You need to make the Value property public to get or set it from outside the class:
public string Value { get; set; }
The classes are not static, so you need to instantiate them to set their properties or use their methods:
var parameters = new MyClass.Parameters();
parameters.Value = "Hello World !";
var methods = new MyClass.Methods();
methods.MyMethod();
The same applies here:
public void MyMethod()
{
var parameters = new MyClass.Parameters();
Window.Title = parameters.Value;
}
But I suspect you actually want MyClass to have its own instances of these classes. So you can add properties for them:
public Properties Properties { get; set; }
public Methods Methods { get; set; }
Then instantiate them somehow (like in the constructor):
public MyClass()
{
Parameters = new Parameters();
Methods = new Methods();
}
If you do steps 1, 4 and 5, the code you have in MainClass should work.
Create a constructor that force the user to add a Value when initiating the class
public class MyClass
{
public string Value { get; set; }
public MyClass(string value)
{
Value = value;
}
public class Methods
{
public void MyMethod()
{
Window.Title = Value;
}
}
}
and call it like this
MyClass myclass = new MyClass("Hello World !");
myclass.Methods.MyMethod();
System.Threading.Thread.Sleep(Timespan.FromSeconds(10));
MyClass myclass2 = new MyClass("Hello World Again !");
myclass2.Methods.MyMethod();
You can declare the properties and methods all within the class:
public class MyClass
{
public MyClass()
{
// Set any initial values
}
public string Value { get; set;}
public void MyMethod()
{
Window.Title = Value;
}
}
And then to use it:
public class MainClass
{
MyClass myclass = new MyClass();
myclass.Value = "Hello World !";
myclass.MyMethod();
System.Threading.Thread.Sleep(Timespan.FromSeconds(10));
MyClass myclass2 = new MyClass();
myclass2.Value = "Hello World Again !";
myclass2.MyMethod();
}
Or to be more succinct:
public class MainClass
{
MyClass myclass = new MyClass {
Value = "Hello World !"
};
myclass.MyMethod();
System.Threading.Thread.Sleep(Timespan.FromSeconds(10));
MyClass myclass2 = new MyClass {
Value = "Hello World Again !"
};
myclass2.MyMethod();
}
UPDATE
If you absolutely need the classes split (although I wouldn't recommend it), then you need to pass your value into the method class to use it. There are a couple of approaches. Either you have to pass the value down into you methods class (not a very elegant approach):
public class MyClass
{
public string Value { get; set;}
public Methods methods {get; set;)
public MyClass(string value)
{
methods = new Methods(value);
Value = value;
}
public class Methods
{
public string Value { get; set;}
public Methods(string value)
{
Value=value;
}
public void MyMethod()
{
Window.Title = Value;
}
}
}
Or make MyMethod() a static method and pass in the value to use:
public class MyClass
{
public string Value { get; set;}
public MyClass(string value)
{
methods = new Methods(value);
Value = value;
}
}
public static class Methods
{
public static void MyMethod(string Value)
{
Window.Title = Value;
}
}
public class MainClass
{
MyClass myclass = new MyClass {
Value = "Hello World !"
};
Methods.MyMethod(myclass.Value);
System.Threading.Thread.Sleep(Timespan.FromSeconds(10));
MyClass myclass2 = new MyClass {
Value = "Hello World Again !"
};
Methods.MyMethod(myclass2.Value);
}
Both ways are not best practice though as, when you start building more complex classes, having the properties and methods in different places will cause a load of headaches.
I have an object that I want to check whether it contains default values or not, in the below code but that doesn't cut it.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyClass()
{
this.Value = 10;
}
}
I have also used Object.ReferenceEquals() but that doesn't cut it as well.
This is the fiddle I am working on.
Is there a way to check whether an object contains default values, or if the object is empty?
Edit: In case of an newly initialized object with many nested properties, how to check whether they contain a default value or not?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
MyClass obj1 = new MyClass();
MyClass obj2 = null;
if(obj1 == new MyClass())
Console.WriteLine("Initialized");
if(Object.ReferenceEquals(obj1, new MyClass()))
Console.WriteLine("Initialized");
}
}
}
public class MyClass
{
public int Value {get; set; }
public MyNestedClass MyProperty { get; set; }
public MyClass()
{
this.Value = 10;
this.MyProperty = new MyNestedClass();
}
}
public class MyNestedClass
{
public string SomeStringProperty { get; set; }
public MyNestedClass()
{
this.SomeStringProperty = "Some string";
}
}
Here is the fiddle in the case of nested objects.
You can achieve your goal by overriding Equals and GetHashCode, creating and saving an immutable "default" instance, and comparing the value to it:
public class MyClass {
public static readonly MyClass DefaultInstance = new MyClass();
public int Value { get; set; }
public MyClass() {
this.Value = 10;
}
public override int GetHashCode() {
return Value.GetHashCode();
}
public override bool Equals(Object obj) {
if (obj == this) return true;
var other = obj as MyClass;
return other?.Value == this.Value;
}
}
Now you can check if the instance is equal to a newly created one by calling
if (MyClass.DefaultInstance.Equals(instanceToCheck)) {
... // All defaults
}
You can change what it means for an instance to be "default" by altering DefaultInstance object.
Note: this trick works well only with immutable MyClass. Otherwise some code could perform MyClass.DefaultInstance.Value = 20 and change the "default" object.
Here is one method using JSON serialization that allows you to check if the objects are equal or not:
DotNetFiddle:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var defaultObj = new MasterObject();
var notDefaultObject = new MasterObject();
var defaultJson = JsonConvert.SerializeObject(defaultObj);
var notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("First Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
notDefaultObject.Sub1.SomeObject.SomeOtherValue = "Not a default Value";
notDefaultJson = JsonConvert.SerializeObject(notDefaultObject);
Console.WriteLine("Second Test");
if (defaultJson == notDefaultJson)
Console.WriteLine("Same thing");
else
Console.WriteLine("Not same thing");
}
}
public class MasterObject
{
public SubObject1 Sub1 { get; set; }
public SubObject2 Sub2 { get; set; }
public string SomeString { get; set; }
public MasterObject()
{
Sub1 = new SubObject1();
Sub2 = new SubObject2();
SomeString = "Some Default String";
}
}
public class SubObject1
{
public string SomeValue { get; set; }
public SubObject2 SomeObject { get; set; }
public SubObject1()
{
SomeObject = new SubObject2();
SomeValue = "Some other Default String";
}
}
public class SubObject2
{
public string SomeOtherValue { get; set; }
public SubObject2()
{
SomeOtherValue = "Some default";
}
}
Output:
First Test
Same thing
Second Test
Not same thing
What is happening is that you serialize the default object and then you make changes to the "not default object", re-serialize and compare again. This can be slow because you are generating strings, but as long as all the sub-objects can be serialized this will be the simplest way to compare if an object is "default" (what you get from new) or has been modified.
I have following code:
public class A
{
public int MyProperty {get; set;}
}
public class B
{
A myInstance = new A();
myInstance.MyProperty = 10;
}
public class C
{
public void InvokeA()
{
//How to access MyPropery here?
BInstance = new B();
Console.WriteLine(B.myInstance.MyProperty.ToString());
}
}
I'm looking for a way to access MyProperty as written above. Inheritance is not an option since my class C is already inherited from some base class. A way without declaring any of the given classes as static would be nice!
Thanks,
Orz
Consider following classes:
public class A
{
public int MyProperty { get; set; }
}
public class B
{
public A GetAInstance()
{
A myInstance = new A();
myInstance.MyProperty = 10;
return myInstance;
}
}
public class C
{
private B BInstance;
public void InvokeA()
{
BInstance = new B();
Console.WriteLine(BInstance.GetAInstance());
}
}
and then you will create your C instance in Main:
static void Main(string[] args)
{
C cInstance = new C();
cInstance.InvokeA();
}
In order to accomplish your goal, you need to expose B.MyInstance as a property of the B class, just like you exposed A.MyProperty as a property of the A class.
Edit: Per the comments of others regarding use of the static keyword, here's what you might want your code to look like:
public class A
{
public int MyProperty { get; set; }
}
public static class B
{
static B()
{
MyInstance = new A();
MyInstance.MyProperty = 10;
}
public static A MyInstance { get; set; }
}
public class C
{
// not sure what your intention is here
public C()
{
System.Console.WriteLine(B.MyInstance.MyProperty.ToString()); // "10\n"
}
}
Yes. You can inherits classes from A to B something like this:
public class A
{
public int MyProperty {get; set;}
}
public class B : A
{
public B()
: A()
{
MyProperty = 1;
}
}
Now you can do:
(new B()).MyProperty
Or use Singleton approach to resolve:
public class B
{
private static _a;
public class A
{
public int MyProperty {get; set;}
}
public static A AA {
if (_a == null) {
_a = new A();
}
return _a;
}
}
This implmentation will return
B.A.MyProperty.ToString();
I'm trying to create a class that has fields in it that are of an anonymous type. (This is for Json deserialization.)
I can't find a syntax that the compiler will accept. I'm trying:
class Foo {
var Bar = new {
int num;
}
var Baz = new {
int[] values;
}
}
This is supposed to represent this example Json object:
{
"Bar": { "num": 0 }
"Baz": { "values": [0, 1, 2] }
}
Is this even possible, or must I declare each class normally with a full class identifier?
You can declare a field using an anonymous type initializer... you can't use implicit typing (var). So this works:
using System;
class Test
{
static object x = new { Name = "jon" };
public static void Main(string[] args)
{
Console.WriteLine(x);
}
}
... but you can't change the type of x to var.
Yes it is possible, here is EXAMPLE
var Bar = new {num = 0};
var Baz = new {values = new List<int>()};
var Foo = new {Bar, Baz};
Console.WriteLine(JsonConvert.SerializeObject(Foo));
Of Course you can type it in one line
var Foo = {Bar = new {num = 0}, Baz = new {values = new List<int>()}};
Edit updated .Net fiddle with using Foo as class
No, this is not possible. The most straightforward way to do this is to simply create classes like you said. This is what I'd recommend.
void Main()
{
Console.WriteLine(JsonConvert.SerializeObject(new Foo { Bar = new Bar {
num = 0
},
Baz = new Baz { values = new[] { 0, 1, 2 } }
})); // {"Bar":{"num":0},"Baz":{"values":[0,1,2]}}
}
public class Foo {
public Bar Bar { get; set; }
public Baz Baz { get; set; }
}
public class Bar {
public int num { get; set; }
}
public class Baz {
public int[] values { get; set; }
}
Another approach, which loses static type checking, is typing it as object or dynamic:
void Main()
{
JsonConvert.SerializeObject(new Foo { Bar = new {
num = 0
},
Baz = new { values = new[] { 0, 1, 2 } }
}); // {"Bar":{"num":0},"Baz":{"values":[0,1,2]}}
}
class Foo {
public object Bar { get; set; }
public object Baz { get; set; }
}
It would probably be possible to write a custom JsonConverter to serialize a class like this as you wish (since each anonymous type in your example only has one real value inside it; if your real types are more complex, this won't work for those).
[JsonConverter(typeof(MyFooConverter))]
class Foo {
public int Bar { get; set; }
public int[] Baz { get; set; }
}
Please excuse bursts of stupidity as I learn the intricacies of C# / .NET
Say I have three classes with multiple static properties (more than three but for arguments sake..)
CLASS FOO
public static A
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
CLASS BAR
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
CLASS YOO
{
get / set A;
}
public static B
{
get / set B;
}
public static C
{
get / set C;
}
And from another class I need to update one or several static properties in each class multiple times... How do I keep from writing multiple SWITCH statments like this...
public void updateVarx(string class, string varx)
{
string y = 'class'
SWITCH (y)
{
case FOO:
FOO.A = Varx;
break;
case BAR:
BAR.A = Varx;
break;
case YOO:
YOO.A = Varx;
break;
}
}
And then another one when I want to update B varY:
public void updateVary(string class, string vary)
{
string y = 'class'
SWITCH (y)
{
case FOO:
FOO.B = Vary;
break;
case BAR:
BAR.B = Vary;
break;
case YOO:
YOO.B = Vary;
break;
}
}
Since you are learning .net/c#, I guess i should warn you, using static properties is probably not the way to go in object oriented programming.
Static is global state and is dangerous. If you end up using multi-threaded code, you have to be super careful. If you need only one instance, just instantiate one, but don't go creating static properties on a class, unless you have a pretty good reason to add them (And I can't think of any right now).
In fact, in well designed, object oriented code you sould probably not have many if, switch, getters or setters either.
Let's say you need different behaviors on your classes, you can do it this way.
Interface ISecurity {
void UpdateVarX(int value);
void UpdateVarY(int value);
int GetValueX();
int GetValueX();
}
class Foo:ISecurity {
// Implement methods of the interface
}
class Bar:ISecurity {
// Implement methods of the interface
}
class Yoo:ISecurity {
// Implement methods of the interface
}
// This class is the class that uses your other classes
class Consumer
{
private ISecurity sec;
public Consumer(ISecurity sec) {
sec.UpdateVarX(25);
}
}
Or if as in your example, all your static classes have the same properties:
public class Settings {
public int A {get; set;}
public int B {get; set;}
public int C {get; set;}
}
public class NeedsToUseOtherClass {
public NeedsToUseOtherClass() {
Settings foo = new Settings();
Settings bar = new Settings();
Settings yoo = new Settings();
foo.setA(25);
}
}
Maybe I am not understanding the problem but if all your classes have the same exact properties then you can just pass the object (FOO, BAR, or YOO) into UpdateVarx or UpdateVary methods and just implement an interface? Something along these lines:
public class FOO : IHasStatus
{
public A
{
get / set A;
}
public B
{
get / set B;
}
public C
{
get / set C;
}
}
public void updateVarx(IHasStatus someObject, string varx)
{
someObject.A = varx;
}
public void updateVary(IHasStatus someObject, string vary)
{
someObject.B = vary;
}
If you don't need the concrete classes, you can abstract out the logic like so:
public class Status {
public string A {
get; set;
}
public string B {
get; set;
}
public string C {
get; set;
}
}
public static class StatusManager {
private static Dictionary<string, Status> statusMap = new Dictionary<string,Status>();
public static Status GetStatus(string name) {
Status status;
if (!statusMap.TryGetValue(name, out status))
statusMap[name] = status = new Status();
return status;
}
public static void SetStatus(string name, Status status) {
statusMap[name] = status;
}
public static void UpdateVarx(string name, string varx) {
GetStatus(name).A = varx;
}
// ...
}
If you are a fan of the javascript way of solving multiple switch cases like this
you can always wrap up the switch handlers as Actions and toss them in a Dictionary.
For example : (Source obtained from here)
public class SwitchCase : Dictionary<string,Action>
{
public void Eval(string key)
{
if (this.ContainsKey(key))
this[key]();
else
this["default"]();
}
}
//Now, somewhere else
var mySwitch = new SwitchCase
{
{ "case1", ()=>Console.WriteLine("Case1 is executed") },
{ "case2", ()=>Console.WriteLine("Case2 is executed") },
{ "case3", ()=>Console.WriteLine("Case3 is executed") },
{ "case4", ()=>Console.WriteLine("Case4 is executed") },
{ "default",()=>Console.WriteLine("Default is executed") },
};
mySwitch.Eval(c);
Below code uses all kinds of hacks, not really recommended in production code unless you have a very good reason.
using System;
using System.Linq;
namespace ConsoleApplication1
{
static class Program
{
private static void SetStaticProperty(string className, string propName, string varx)
{
//This sucks, I couldnt find the namespace with easily through reflection :(
string NAMESPACE = "ConsoleApplication1";
Type t = Type.GetType(NAMESPACE + "." + className);
t.GetProperties().Where(p => p.Name == propName).First().SetValue(null, varx, null);
}
public static void updateVarx(string className, string varx)
{
SetStaticProperty(className, "A", varx);
}
public static void updateVary(string className, string vary)
{
SetStaticProperty(className, "B", vary);
}
static void Main(string[] args)
{
updateVarx("Foo", "FooAstring");
updateVarx("Bar", "BarAstring");
updateVarx("Yod", "YodAstring");
updateVary("Foo", "FooBstring");
updateVary("Bar", "BarBstring");
updateVary("Yod", "YodBstring");
Console.WriteLine(Foo.A);
Console.WriteLine(Foo.B);
Console.WriteLine(Bar.A);
Console.WriteLine(Bar.B);
Console.WriteLine(Yod.A);
Console.WriteLine(Yod.B);
Console.ReadLine();
}
}
class Foo
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
class Bar
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
class Yod
{
public static string A { get; set; }
public static string B { get; set; }
public static string C { get; set; }
}
}
You can use dictionary as configuration and remove the switch statement
Create a dictionary and add append data as below for mapping
//Have dictionary setted up
Dictionary<string, dynamic> m_Dictionary = new Dictionary<string, dynamic>();
m_xmlDictionary.Add("classA",FOO);
m_xmlDictionary.Add("classB",BAR);
m_xmlDictionary.Add("classC",BAR);
//Have dictionary setted up
//change the function as below
public void updatevarx(string class, string varx)
{
m_Dictionary[class].A=varx // Replaced switch statement
}
//while calling use
updatevarx("classC","abc!");// This will assign BAR.A with abc!