Is there a way to make a class return one of its fields by default like that:
public class TestClass
{
public string something;
}
TestClass test = new TestClass();
test = "alpha"; // "alpha" string is assigned to "something"
Console.Write(test); // test returns "alpha" string from "something"
How to make this work?
For all those saying that's impossible,)
public class TestClass
{
public string something;
public static implicit operator TestClass(string s) => new TestClass { something = s};
public static implicit operator string(TestClass testClass) => testClass.something;
}
Usage:
TestClass test = new TestClass();
test = "alpha";
Console.WriteLine(test);
Gives:
alpha
Note: Console.WriteLine takes test as string and calls Console.WriteLine(string value) overload thanks to implicit conversion.
You can't make "a class return a field", but you can override its ToString method, so when it's printed with something like Console.Write you'll get the output you want:
public class TestClass
{
public string Something {get; set;}
public override string ToString()
{
return Somethig;
}
}
I would prefer to use the constructor and overload method ToString(), so you get an immutable object.
public class TestClass
{
private readonly string something;
public TestClass(string something)
{
this.something = something;
}
public override string ToString()
{
return something;
}
}
TestClass test = new TestClass("alpha");
Console.Write(test);
Is there a way to make a class return one of its fields by default?
No. Classes are not designed to return any value.
An alternative way to achieve what you mentioned in your question is defining property with get; set;, something like:
public class TestClass
{
public string Something { get; set; }
}
which you can use like:
TestClass test = new TestClass();
test.Something = "alpha"; // "alpha" string is assigned to "something"
Console.Write(test.Something); // test returns "alpha" string from "something"
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 am trying to instantiate a new object using the moq that I have set up but I am not getting the data I've set up in moq. Why?
For instance: I've set up MyMethod() to true in mock. But when I create the new instance from mock.object I am getting false for MyMethod().
Interface:
public interface IMyClass
{
bool MyMethod();
}
Class
public class MyClass : IMyClass
{
public MyClass(IMyClass myClass)
{
}
public bool MyMethod()
{
return false;
}
public string DoSomething()
{
if(MyMethod() == false)
{
// do something
return "did something";
}
else
{
// do something else
return "did something else";
}
}
}
TestMethod
[TestMethod]
public void MyMethodTest()
{
var moq = new Mock<IMyClass>();
moq.Setup(m => m.MyMethod()).Returns(true);
var sut = new MyClass(moq.Object);
Assert.AreEqual(sut.DoSomething(), "did something else"); // Actual: "did something" Expected: "did something else"
}
The test fails because you are not assigning any value in the class to the public member being compared.
MyClass.MyProperty is never assigned a value, so in
Assert.AreEqual(sut.MyMethod(), true);
sut.MyMethod() will be false
You would need to refactor the class to use the value from the injected interface and assign it to the respective member.
public class MyClass : IMyClass {
public bool MyProperty { get; set; }
public bool MyMethod() {
return MyProperty;
}
public MyClass(IMyClass myClass) {
this.MyProperty = myClass.MyProperty; // assigning value to property
}
}
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 want a constructor call to only allow a limited range of "extensions". Let's say I have these 2 classes:
public class Foo
{
public Foo(Extension ext)
{
// do something
}
}
public class Extension
{
public const string TXT = ".txt";
public const string XML = ".xml";
}
So, when another developer would want to use Foo he can only do so with the values from the Extension class like so:
Foo foo = new Foo(Extension.TXT);
But when trying to do this I get an IDE error saying: "cannot convert from 'string' to '<ProjectName>.Extension'.
As a "workaround" I could change my Extension class to something like this:
public class Extension
{
public enum File
{
TXT,
XML
}
}
and use it like this:
Foo foo = new Foo(Extension.File.TXT);
which works perfectly fine but what I do not like is that the call is one level longer (class -> enum -> element instead of class -> element).
So, the questions is is my workaround actually the only valid, correct or best practice solution?
You can use a Java style enum class
public class Extension
{
string _Extension = null;
private Extension(string ext)
{
_Extension = ext;
}
public static Extension TXT
{
get { return new Extension(".txt"); }
}
public static Extension XML
{
get { return new Extension(".xml"); }
}
public override string ToString()
{
return _Extension;
}
public override bool Equals(object obj)
{
var e = obj as Extension;
if (e == null) return false;
return e._Extension == this._Extension;
}
public override int GetHashCode()
{
return _Extension.GetHashCode();
}
}
The first example has Extension being used as a class with a couple of string constants. The second example uses an enum in lieu of the constants.
public class Foo
{
// this .ctor expects a type of Extension, not a string.
public Foo(Extension ext)
{
// do something
}
}
// This class has only constant string values.
public class Extension
{
public const string TXT = ".txt";
public const string XML = ".xml";
}
Attempting to pass in a string to the above .ctor will not work as it is expecting a type of Extension, not a string.
// this passes in a string, not a type.
Foo foo = new Foo(Extension.TXT);
As you are wanting to limit the values available to the Foo .ctor, then use an enum as you have in your 2nd example:
public class Foo
{
public Foo(File ext)
{
// do something
}
}
public enum File
{
TXT,
XML
}
Then this will work as expected:
Foo foo = new Foo(File.TXT);
Why not to declare enum outside of class Foo and without any special class like extension?
public enum Extension
{
TXT,
XML
}
public class Foo
{
public Foo(Extension ext)
{
// do something
}
}
Then when you are constructing a Foo object you can simply do:
Foo foo = new Foo(Extension.TXT);
You could define a default constructor and implicit operator for string to Extension. Eg. something like:
public class Extension
{
public const string TXT = ".txt";
public const string XML = ".xml";
private _value;
public Extension(string value){if(value == TXT || value == XML) _value = value; else throw new NotImplementedException();}
public static implicit operator string(Extension value){return _value;}
public static implicit operator Extension(string value){if(value == TXT || value == XML) _value = value; else throw new NotImplementedException();}
}
that way you could call Foo(".txt") or Foo(Extension.TXT)
or you could define TXT as an instance of Extension:
public class Extension
{
public const Extension TXT = new Extension(".txt");
public const Extension XML = new Extension(".xml");
public Value{get;private set;}
public Extension(string value){Value = value;}
}
Just change the first declaration of Extesion from Class to Enum
Lets suppose we have these classes:
class A {
public string attr = "Class A";
public static void getAttribute(){
self currentClass = new self(); // equivalent to php
Console.Write("Attribute : " + currentClass.attr);
}
}
Class B : A {
public string attr = "Class B";
}
B = new B();
B.getAttribute();
I want B.getAttribute(); to print Attribute: Class B. How can I do this?
This is fundamentally impossible.
B.getAttribute() compiles to A.getAttribute().
I probably know what you are trying to do, but I have to tell you that this kind of PHP approach makes no sense in C#. I discourage you from using it.
public class A
{
private String attr = "Class A";
public static String getAttribute()
{
return (new A()).attr;
}
}
public class B : A
{
private String attr = "Class B";
public static String getAttribute()
{
return (new B()).attr;
}
}
You get the current class instance by the 'this' keyword. Obviously you cannot access that in a static method since by definition a static method executes without the context of a particular instance.
On the other hand, to access a member variable/property/method from inside the same class, you don't need the 'this' keyword at all, since it's implicit.
If you're asking how to do something like that in C#, I think the answer would be along these lines:
public class A
{
public virtual string attr
{
get { return "Class A" }
}
public void getAttribute(){
Console.Write("Attribute : " + attr);
}
}
public class B : A
{
public override string attr
{
get { return "Class B"; }
}
}
var b = new B();
b.getAttribute();
Regarding my comment in the other answer, if you needed getAttribute to be static, you could implement it this way:
public static void getAttribute(A obj){
Console.Write("Attribute : " + obj.attr);
}
You would then call it like this:
var b = new B();
A.getAttribute(b);