An error has been occurred while try changing the string property inside class,
but if assign ('f.StartTime' to a string variable it's work but doesn't change the 'StartTime' property)
like:
string x = f.StartTime;
ChangeText(ref x); // There's no error, but f.StartTime didn't change.
//Unless:
f.StartTime = x;
of course it's Fake Method...
so i want perform the following code.
public class MainClass
{
public class Foo
{
public string StartTime { get; set; }
public string ToTime { get; set; }
}
private void ChangeText(ref string Time)
{
Time = DateTime.Now.ToString();
}
public void SetClassObjects()
{
Foo f = new Foo()
{
StartTime = "Any Text",
ToTime = "Any Text"
};
ChangeText(ref f.StartTime);
// An error: A property, indexer or dynamic member access may not be passed as an out or ref parameter
}
Strings are immutable, assigning f.StartTime to x creates a copy of the value not of the reference. Hence you need to re-assign f.StartTime. The ref inclusion will correctly re-assign the reference x (to actually point at a new string under x), but the reference to f.StartTime is lost due to the value-type semantics of strings. Note that strings are reference types, they just follow the semantics of value types.
I would shy away from providingstring as a ref in this instance and instead do something like:
f.StartTime = GetText();
private string GetText()
{
return DateTime.Now.ToString();
}
Or alternatively pass Foo into the ChangeText method:
private void ChangeText(Foo fooItem)
{
fooItem.Time = DateTime.Now.ToString();
}
Then just ChangeText(f);.
If you want to provide a generic mechanism for mutating a property string, you could have an interface:
public interface ICanHaveMyTextChanged
{
void ChangeText(string newText);
}
Which Foo implements:
class Foo : ICanHaveMyTextChanged
{
public string StartTime { get; private set; }
public void ChangeText(string newText)
{
StartTime = newText;
}
}
And then specify the interface as the argument instead of Foo:
private void ChangeText(ICanHaveMyTextChanged item)
{
item.ChangeText(DateTime.Now.ToString());
}
And call thus:
var f = new Foo();
ChangeText(f);
Now any class that implements this interface can have it's text changed.
Related
I have a class where I used implicit operator to initialize the class when string value assigned like this
MyClass db = "";
My class is
public class MyClass
{
public static implicit operator MyClass(string value)
{
var result = new MyClass()
{
Value = value
};
return result;
}
public string Value { get; set; }
}
This works fine, but when I use MyClass as one of optional parameter in method I can not assign default value.
Example
public class Test
{
public void TestMethod(MyClass my="Default")
{
}
}
what I need to add in my class so that TestMethod(MyClass my="Default") can also work under method paramater
I have an interface that extends some other interface, like this:
interface IBase
{
int Id { get; set; }
string Name { get; set; }
}
interface IExtended : IBase
{
bool IsChecked { get; set; }
}
Then I use base interface as a parameter in a delegate function that is also a parameter to class constructor, like this:
public class SomeClass
{
private IBase _model;
private Func<IBase, string> _handler;
public SomeClass(IBase model, Func<IBase, string> handler)
{
_model = model;
_handler = handler;
}
public string ExecuteHandler()
{
return _handler(model);
}
}
Interface implementations:
public class BaseImplementation : IBase
{
int Id { get; set; }
string Name { get; set; }
public BaseImplementation(int id, string name)
{
Id = id;
Name = name;
}
}
public class ExtendedImplementation : IExtended
{
int Id { get; set; }
string Name { get; set; }
bool IsChecked { get; set; }
public BaseImplementation(int id, string name, bool isChecked)
{
Id = id;
Name = name;
IsChecked = isChecked;
}
}
Intended use:
BaseImplemetation baseModel = new BaseImplementation(1, "base");
ExtendedImplemetation extendedModel = new ExtendedImplementation(2, "extended", true);
SomeClass someClass1 = new SomeClass(baseModel, (IBase arg) => {
Console.Write("Remember, " + arg.name + ", YOLO!");
});
SomeClass someClass2 = new SomeClass(extendedModel, (IExtended arg) => {
Console.Write(arg.name + ", YOLO! You're " + (arg.IsChecked) ? "checked!" : "not checked!");
});
string res1 = someClass1.ExecuteHandler();
string res2 = someClass2.ExecuteHandler();
But that ( doesn't work, even though implementation of IExtended would necessarily implement everything that is defined by IBase interface. Why is that so and how would I bypass this and get the result I want?
EDIT:
I think I got it now.
I thought that Func<IBase, string> is equal to Func<IExtended, string> because IExtended of course implements everything that IBase does, so there should be no problem, right? Implementation as I wanted it to be and is listed in my example would of course work just fine.
BUT! The problem is that someClass2 can't be constructed like that because, as #Servy mentioned, delegate function could do something like this:
SomeClass someClassWrong = new SomeClass(baseModel, (IExtended arg) => {
if (arg.IsChecked) {
// gotcha, baseModel doesn't have IsChecked property!
}
});
EDIT 2:
Thank you everybody for you help and sorry for constant editing and giving wrong example sof what I want :D
But that doesn't work, even though implementation of IExtended would necessarily implement everything that is defined by IBase interface. Why is that so and how would I bypass this and get the result I want?
When SomeClass invokes that delegate it might not actually pass an IExtended instance. It's allowed to provide any IBase instance as the parameter, so if it provides one that doesn't implement IExtended, then what would you expect your delegate to do?
If SomeClass is always going to pass an IExtended instance, then modify the delegate it accepts in its constructor accordingly, so that the callers always know they're getting an IExtended instance as a parameter.
You can simply define a delegate that knows the IBase is really an IExtended:
SomeClass someClass = new SomeClass((IBase arg) => { (arg as IExtended).DoSomethingOnlyExtendedKnowsAbout(); });
This is potentially unsafe, but if you somehow can enforce that the arg passed to that specific lamda will always be an IExtended then there is no harm. You could also provide a safety mechanism in the lambda itself and manage it accordingly up the call stack:
SomeClass someClass = new SomeClass((IBase arg) => { (arg as IExtended)?.DoSomethingOnlyExtendedKnowsAbout(); });
I don't see the problem. Based on the code you have, the following works as intended:
public class SomeClass
{
public SomeClass(Func<IBase, string> handlerFcn)
{
// something gets done
this.Handler=handlerFcn;
}
public Func<IBase, string> Handler { get; set; }
}
public static class Program
{
static void Main(string[] args)
{
var s1 = new SomeClass((x) => x.SomeMethod());
var xt = new ExtendedClass();
var result = s1.Handler(xt);
// result = "yolo extended edition!"
}
}
I think you were trying to use the concrete class ExtendedClass in the lambda definition and that won't work unless you define it as a closure.
I am trying to use setter and getter. When i debug, the value gets set but when i try to retrieve, it gets null value.
Class1.cs
private string setMAX;
public string SETMax
{
get
{
return setMAX;
}
set
{
setMAX = value;
}
}
private string value1;
public string MaxValue
{
get
{
return value1;
}
set
{
value1= value;
}
}
Class2.cs
Class1.SETMax = Class1.value1; //This gets set
Class3.cs
//When i debug, first Class1.cs and Class2.cs completes, then it comes in Class3.cs
string max = Class1.SETMax; //I GET NULL here.
I dont know where I am wrong here.Can anyone please explain me ?
You are referencing File1 as an instance. You are probably referencing different instances. You probably want static properties.
private static string setMAX;
public static string SETMax
{
get
{
return setMAX;
}
set
{
setMAX = value;
}
}
I think you have a few things mixed up so lets start from the beginning
Class1.SETMax = Class1.value1;
// for a start you are assigning a
// private variable to a public one
// via the Class definition I'm not even sure how that compiles.
Have a look here see if this makes sense to you
// This is a Class definition
public class Class1 {
public string SETMax {get; set;}
public int MaxValue {get; set;}
}
// This is your application
public class MyApp{
// this is a private field where you will assign an instance of Class1
private Class1 class1Instance ;
public MyApp(){
//assign the instance in the constructor
class1Instance = new Class1();
}
public void Run {
// now for some fun
class1Instance.SETMax = "Hello";
Console.WriteLine(class1Instance.SETMax); // outputs "Hello"
var localInstance = new Class1();
localInstance.SETMax = class1Instance.SETMax;
Console.WriteLine(localInstance.SETMax); // outputs "Hello"
}
}
Consider this code:
public string Variable1 { get; set;}
public int Variable2 { get; set;}
public void Function()
{
// Has been Variable1 Initialized?
}
Inside the function, I want to know if a value has been sent to Variable1 & Variable2, prior to the function call,
even if the DEFAULT values have been sent, that's ok (null for string & 0 for int)
Consider using a simple wrapper like this:
public struct AssignableProperty<T>
{
private T _value;
public T Value
{
get { return _value; }
set
{
WasAssigned = true;
_value = value;
}
}
public bool WasAssigned { get; private set; }
public static implicit operator AssignableProperty<T>(T data)
{
return new AssignableProperty<T>() { Value = data };
}
public static bool operator ==(AssignableProperty<T> initial, T data)
{
return initial.Value.Equals(data);
}
public static bool operator !=(AssignableProperty<T> initial, T data)
{
return !initial.Value.Equals(data);
}
public override string ToString()
{
return Value.ToString();
}
}
Then your class'll look like this:
public class Test
{
public AssignableProperty<string> Variable1 { get; set; }
public AssignableProperty<int> Variable2 { get; set; }
public void Function()
{
if(Variable1.WasAssigned&&Variable2.WasAssigned)
//do stuff
}
}
You can go further and add throw Exception or contract to getter, so if somebody'll try to access uninitialized value it'll throw an exception or show you warning
Some basics about default value in C#:
When an instance of a class (or struct) is created, all fields are initialized to their respective default value.
For reference types, it will be null. For value types, it will be equivalent to 0. This is easily explains as the memory management ensures that new allocated memory is initialized to 0x0 bytes.
Auto-properties hide the generated field, but there is one. So the same rules apply.
Now to answer your question, the best way to make sure that values are initialized is to make a constructor with one parameter for each field/property and to hide the default constructor with no parameters:
public Yourtype(String param1, Int32 param2)
{
this.Variable1 = param1;
this.Variable2 = param2;
}
private Yourtype() { }
Other alternatives is described in #Sean and #Alex answers if only a subset of properties/fields needs to be initialized/checked. But this hides some overhead (one bool for each property/field and some indirection).
For the reference types you'll need to add a flag:
string m_Variable1;
bool m_IsVariable1Set;
public string Variable1
{
get{return m_Variable1;}
set{m_IsVariable1Set = true; m_Variable1 = value;}
}
For the value types you can use a nullable value
int? m_Variable2;
int Variable2
{
get{return m_Variable2.GetValueOrDefault();}
set{m_Variable2 = value;}
}
Which you can then check to see if it's been set by using m_Variable2.HasValue.
Well you can simply do a check on both variables to see if they have any value assigned to them in your function
public void Function()
{
if (String.IsNullOrEmpty(Variable1) && Variable2 ==0 )
{
// Variables are not assigned
}
}
I have a class that requests that when called a string is sent when requesting / initializing it.
class Checks
{
public Checks(string hostname2)
{
// logic here when class loads
}
public void Testing()
{
MessageBox.Show(hostname2);
}
}
How would it be possible to take the string "hostname2") in the class constructor and allow this string to be called anywhere in the "Checks" class?
E.g. I call Checks(hostname2) from the Form1 class, now when the Checks class is initialized I can then use the hostname2 string in my Checks class as well
Declare a member inside the class and assign the value you passed to the member inside the constructor:
class Checks
{
private string hostname2;
public Checks(string hostname2)
{
this.hostname2 = hostname2; // assign to member
}
public void Testing()
{
MessageBox.Show(hostname2);
}
}
If you also need to have outside access, make it a property:
class Checks
{
public string Hostname2 { get; set; }
public Checks(string hostname2)
{
this.Hostname2 = hostname2; // assign to property
}
public void Testing()
{
MessageBox.Show(Hostname2);
}
}
Properties start with a capital letter by convention. Now you can access it like this:
Checks c = new Checks("hello");
string h = c.Hostname2; // h = "hello"
Thanks to Andy for pointing this out: if you want the property to be read-only, make the setter private:
public string Hostname2 { get; private set; }
You need to copy the constructor argument in a class variable:
class Checks {
// this string, declared in the class body but outside
// methods, is a class variable, and can be accessed by
// any class method.
string _hostname2;
public Checks(string hostname2) {
_hostname2 = hostname2;
}
public void Testing() {
MessageBox.Show(_hostname2);
}
}
You can expose a public property to retun the hostname2 value which is the standard for exposing your private varibles
class Checks
{
private string _hostname;
public Checks(string hostname2)
{
_hostname = hostname2;
}
public string Hostname
{
get { return _hostname; }
}
}