Sorry its a bit vague perhaps but its been bugging me for weeks. I find each project I tackle I end up making what I think is a design mistake and am pretty sure theres a bettwe way.
When defining a class thats serialized from an event source like a sinple json doc definition. Lets call it keys class with various defined integers, bools and strings. i have multiple methods that make use of this and i find that i constantly need to paas this class as an object by means of an overload. So method a calls methods b, method b doesnt need these objects but it calls method c which does... In doing this bad practice im passing these 'keys' objects to method b for the sole purpose of method c accessibility.
Im probably missing one major OOP fundamental :) any guidance or reading would be appreciated as im googled out!!
public class Keys
{
public child Detail { get; set; }
}
public class child
{
public string instance { get; set; }
}
//my main entry point
public void FunctionHandler(Keys input, ILambdaContext context)
{
methodA(input)
}
static void methodA(Keys input)
{
//some-other logic or test that doesn't need Keys object/class if (foo==bar) {proceed=true;}
string foo = methodB(input)
}
static string methodB(Keys input)
{
//here i need Keys do do stuff and I return a string in this example
}
What you do is not necessarily bad or wrong. Remember that in C# what you actually pass are references, not objects proper, so the overhead of parameter passing is really small.
The main downside of long call chains is that the program logic is perhaps more complicated than it needs to be, with the usual maintainability issues.
Sometimes you can use the C# type system to let the compiler or the run time choose the proper function.
The compiler is employed when you overload method() for two different types instead of defining methodA() and methodB(). But they are distinguished by the parameter type, so you need different Key types which may be (but don't have to be) related:
public class KeyA {/*...*/}
public class KeyB {/*...*/}
void method(KeyA kA) { /* do something with kA */ }
void method(KeyB kB) { /* do something with kB */ }
This is of limited benefit; that the functions have the same name is just syntactic sugar which makes it clear that they serve the same purpose.
The other, perhaps more elegant and versatile technique is to create an inheritance hierarchy of Keys which each "know" what a method should do.
You'll need a base class with a virtual method which will be overridden by the inheriting classes. Often the base is an interface just declaring that there is some method(), and the various implementing types implement a method() which suits them. Here is a somewhat lengthy example which uses a virtual Output() method so that we see something on the Console.
It's noteworthy that each Key calls a method of an OutputterI, passing itself to it as a parameter; the outputter class then in turn calls back a method of the calling object. That's called "Double Dispatch" and combines run-time polymorphism with compile-time function overloading. At compile time the object and it's concrete type are not known; in fact, they can be implemented later (e.g. by inventing another Key). But each object knows what to do when its callback function (here: GetData()) is called.
using System;
using System.Collections.Generic;
namespace DoubleDispatch
{
interface KeyI
{ // They actually delegate that to an outputter
void Output();
}
interface OutputterI
{
void Output(KeyA kA);
void Output(KeyExtra kE);
void Output(KeyI k); // whatever this does.
}
class KeyBase: KeyI
{
protected OutputterI o;
public KeyBase(OutputterI oArg) { o = oArg; }
// This will call Output(KeyI))
public virtual void Output() { o.Output(this); }
}
class KeyA : KeyBase
{
public KeyA(OutputterI oArg) : base(oArg) { }
public string GetAData() { return "KeyA Data"; }
// This will compile to call Output(KeyA kA) because
// we pass this which is known here to be of type KeyA
public override void Output() { o.Output(this); }
}
class KeyExtra : KeyBase
{
public string GetEData() { return "KeyB Data"; }
public KeyExtra(OutputterI oArg) : base(oArg) { }
/** Some extra data which needs to be handled during output. */
public string GetExtraInfo() { return "KeyB Extra Data"; }
// This will, as is desired,
// compile to call o.Output(KeyExtra)
public override void Output() { o.Output(this); }
}
class KeyConsolePrinter : OutputterI
{
// Note: No way to print KeyBase.
public void Output(KeyA kA) { Console.WriteLine(kA.GetAData()); }
public void Output(KeyExtra kE)
{
Console.Write(kE.GetEData() + ", ");
Console.WriteLine(kE.GetExtraInfo());
}
// default method for other KeyI
public void Output(KeyI otherKey) { Console.WriteLine("Got an unknown key type"); }
}
// similar for class KeyScreenDisplayer{...} etc.
class DoubleDispatch
{
static void Main(string[] args)
{
KeyConsolePrinter kp = new KeyConsolePrinter();
KeyBase b = new KeyBase(kp);
KeyBase a = new KeyA(kp);
KeyBase e = new KeyExtra(kp);
// Uninteresting, direkt case: We know at compile time
// what each object is and could simply call kp.Output(a) etc.
Console.Write("base:\t\t");
b.Output();
Console.Write("KeyA:\t\t");
a.Output();
Console.Write("KeyExtra:\t");
e.Output();
List<KeyI> list = new List<KeyI>() { b, a, e };
Console.WriteLine("\nb,a,e through KeyI:");
// Interesting case: We would normally not know which
// type each element in the vector has. But each type's specific
// Output() method is called -- and we know it must have
// one because that's part of the interface signature.
// Inside each type's Output() method in turn, the correct
// OutputterI::Output() for the given real type was
// chosen at compile time dpending on the type of the respective
// "this"" argument.
foreach (var k in list) { k.Output(); }
}
}
}
Sample output:
base: Got an unknown key type
KeyA: KeyA Data
KeyExtra: KeyB Data, KeyB Extra Data
b,a,e through KeyI:
Got an unknown key type
KeyA Data
KeyB Data, KeyB Extra Data
Related
I'm studying the uses of this and I think I understand it, at least partially, like when to solve ambiguity and to call methods from the "current" class, but one example from the book I'm reading(Head First C#) is giving me a hard time:
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
In this method, is it safe to say that the this has the function of always refering to whatever object calls the method SpeakTo(), regardless of which class the call is written in?
No... Actually, this in your context refers to the object on which SpeakTo is defined, not the object which calls it.
Let's put it this way:
Object speaker is of the class Speaker which defines the SpeakTo
method,
Object caller is calling the speaker.SpeakTo(), and
Object whoToTalkTo is of the class which defines the TellMe(string, Speaker)
As you can see, whoToTalkTo is expecting the Speaker class instance. Then, the speaker object is precisely that, and it is free to pass this as the argument.
Now we can construct a larger example in which these relations are becoming more obvious:
class Speaker
{
public int Data { get; set; }
public void SpeakTo(Elephant whoToTalkTo, string message)
{
// Passing current instance of this class as the argument
whoToTalkTo.TellMe(message, this);
}
}
This Speaker class contains a piece of state. Now I will use the whoToTalkTo object to change that state:
class Talker
{
public void TellMe(string message, Speaker speaker)
{
speaker.Data = message.Length;
}
}
This implementation is changing the state of one particular object which was passed to it.
Now the ultimate caller comes to the picture, the one which actually selects the Speaker object which will be subjected to the TellMe() method:
class Caller
{
public void DoWork()
{
Talker talker = new Talker();
Speaker one = new Speaker();
Speaker two = new Speaker();
// This sets one.Data to length of "something"
one.SpeakTo(talker, "something");
// This sets two.Data to length of "else"
two.SpeakTo(talker, "else");
Console.WriteLine(one.Data);
Console.WriteLine(two.Data);
}
}
This code will print values 9 and 4, which indicates that the whoToTalkTo has actually been modifying the state of two distinct objects.
In this method, is it safe to say that the "this" has the function of always refering to whatever object calls the method "SpeakTo()", regardless of which class the call is written in?
Nope. this does not refer to the object that calls SpeakTo. It refers to the object on which SpeakTo is called.
I will use some code to clarify this point
class Foo {
public static void Main(String[] args) {
var foo = new Foo();
foo.MyMethod();
}
public void MyMethod() {
var bar = new Bar();
bar.SpeakTo(anElephant, "Hello");
}
}
class Bar {
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
}
According to your statement, this refers to the foo variable that's created in the main method. This is not the case. this actually refers to bar. i.e. the object that's before the method name.
this refers to the current object of the class which has method SpeakTo.
consider the following example:
public class A
{
public void SpeakTo(Elephant whoToTalkTo, string message) {
whoToTalkTo.TellMe(message, this);
}
}
Now if you instantiate an object of A and calls the method SpeakTo it will be like:
A obj = new A();
obj.SpeakTo();
In the method SpeakTo, this refers to the current object, i.e. obj.
The signature of method TellMe should look like:
public void TellMe(string message, A objOfA)
I have an Address class:
public class Address
{
//Some stuff
}
and there's a corresponding *Wrapper class to enforce certain rules on how to
use the Address class:
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
where IWrapped is defined as:
public interface IWrapped<T>
{
T GetWrapped();
}
I have the following generic class for saving these entities (there are other
entities that follow this pattern of Entity and EntityWrapper):
public class GenericRepository
{
private GenericRepository() { }
public static void Add<T>(IWrapped<T> entity)
{
//Do something
}
public static void AddList<T>(IList<IWrapped<T>> entities)
{
//Do something
}
}
and I have this test code:
[Test]
public void UseGenericRepository()
{
AddressWrapper addrW = new AddressWrapper();
addrW.AddrLine1 = "x";
addrW.AddrLine2 = "y";
addrW.AddrLine3 = "z";
addrW.City = "Starling City";
//This works as expected
GenericRepository.Add<Address>(addrW);
IList<AddressWrapper> addrList = new List<AddressWrapper>();
//Fill up the addrList
//This gives error: best overloaded method match has some invalid
//arguments
GenericRepository.AddList<Address>(addrList);
}
AddressWrapped is of type IWrapped<Address> (i.e., it implements it) and
Address is the type parameter being given to the AddList method, so the
types should line up. I know that this is due to my limited knowledge of C#
generics (familiar with Java generics), but can't figure out what's wrong here
--- it should work.
This probably doesn't make any difference, but here's my config:
NHibernate 4.x
.NET Framework (4.5)
This is because of the missing type variance of IList<T>. (IList<int> is not an IList<object>).
Use IEnumerable<T>, because it is covariant:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do something
}
Reason: If you get an instance of List<AddressWrapper>, the compiler doesn't know if it is compatible with any possible implementation of IList<IWrapped<T>>. Assume another class that implements IWrapped<T>. It wouldn't be compatible when writing to the List. Even though you don't write to the list in AddList, the compiler only accepts compatible types. IEnumerable<T> cannot be written, so it can be variant.
Not related to the question I suggest to use covariance for your own interface as well:
public interface IWrapped<out T>
to make IWrapped<Thing> compatible with IWrapped<SpecificThing>.
MSDN: https://msdn.microsoft.com/en-us/library/ee207183.aspx
To make this clear by an example. Would would you expect happen if we had two types implement IWrapped<T>?
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
public class OtherWrapper : IWrapped<MailBox>
{
public MailBox GetWrapped()
{
throw new MailBox();
}
}
And we tried to add them to a third list inside AddList<T>:
public static void AddList<T>(IList<IWrapped<T>> entities)
{
internalList = new List<IWrapped<T>>();
list.AddRange(entities); // BOOM.
}
The type system is keeping you from making a mistake. List<T> isn't covariant exactly for that reason.
At the point at which you're trying to call AddList(), for all the compiler knows, that method may add objects of any type that implements IWrapper<Address> (i.e. types that aren't AddressWrapper) to the passed in list.
That would be bad because the list you're trying to pass to the method doesn't want to contain anything other than AddressWrappers.
NB: Please see the answer by #StefanSteinegger, it is especially enlightening.
What worked for me was changing the way I was defining addrList, from:
IList<AddressWrapper> addrList = new List<AddressWrapper>();
to:
IList<IWrapped<Address>> addrList = new List<IWrapped<Address>>();
However, I am also changing the signature of the GenericRepository.AddList<T>(..) method to take an IEnumerable as that also helps indicate that the input is read-only. So:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do some stuff
}
I've this question about pass some instances by ref or not: here is my problem:
Case 1: simple var like int:
private void button2_Click(object sender, EventArgs e)
{
int nTest = 10;
testInt(nTest);
MessageBox.Show(nTest.ToString());
// this message show me 10
testIntRef(ref nTest);
MessageBox.Show(nTest.ToString());
// this message show me 11
}
private void testInt(int nn)
{
nn++;
}
private void testIntRef(ref int nn)
{
nn++;
}
this is exactly what I think, if I use the ref, the parameter is passed by reference, so if is changed, when I exit from the function, the value is changed...
Case 2: class:
// simple class to understand the reference..
public class cTest
{
int nTest;
public cTest()
{
setTest(0);
}
public void setTest(int n)
{
nTest = n;
}
public int getTest()
{
return nTest;
}
}
// my main code
private void button3_Click(object sender, EventArgs e)
{
cTest tt = new cTest();
tt.setTest(2);
testClass(tt);
// I expect that the message shows me 2, 'cause testClass
// doesn't have (ref cTest test)
MessageBox.Show(tt.getTest().ToString());
}
private void testClass(cTest test)
{
test.setTest(55);
}
and, as written in the comment on the code, I don't have passed my cTest as reference, but the result is the same, the message show me 55 and not 2..
How can I pass a class without reference?
How can I pass a class without reference?
You can't.
You can clone that instance and send it, but it will still be sent by ref...
class - Reference type
struct - Value type.
Reading:
Article about passing variables in C#
Wikipedia about Objects copy- shallow copy + deep copy.
Quoting Jon Skeet C# in depth second edition:
MYTH #3: “OBJECTS ARE PASSED BY REFERENCE IN C# BY DEFAULT”
This is probably the most widely propagated myth. Again, the people who make this
claim often (though not always) know how C# actually behaves, but they don’t know
what “pass by reference” really means. Unfortunately, this is confusing for people who
do know what it means. The formal definition of pass by reference is relatively complicated,
involving l-values and similar computer science terminology, but the important
thing is that if you pass a variable by reference, the method you’re calling can change
the value of the caller’s variable by changing its parameter value. Now remember that the
value of a reference type variable is the reference, not the object itself. You can change
the contents of the object that a parameter refers to without the parameter itself being
passed by reference.
For instance, the following method changes the contents of the
StringBuilder object in question, but the caller’s expression will still refer to the
same object as before:
void AppendHello(StringBuilder builder)
{
builder.Append("hello");
}
When this method is called, the parameter value (a reference to a StringBuilder) is
passed by value. If I were to change the value of the builder variable within the
method—for example, with the statement builder = null;—that change wouldn’t be
seen by the caller, contrary to the myth.
C# in depth Value types and reference types page 46
If you want something like that, you want to use struts instead of classes.
If you just want to make sure that a method can't modify an argument, then you can create a read-only base class:
public abstract class ReadOnlyUser
{
public string GetName() { ... }
}
public class User : ReadOnlyUser
{
public void SetName(string name) { ... }
}
Then you can write the method in such a way that the method body can't modify the argument by mistake:
public void Register(ReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
Of course you can invoke this method with an instance of the User class:
var user = new User(...);
Register(user);
You can also implement a read-only interface:
public interface IReadOnlyUser
{
string GetName();
}
public interface IUser : IReadOnlyUser
{
void SetName(string name);
}
public class User : IUser
{
public string GetName() { ... }
public void SetName(string name) { ... }
}
public void Register(IReadOnlyUser user)
{
string name = user.GetName();
user.SetName("John"); // doesn't compile
}
I am setting up a testing component and trying to keep it generic. I want to use a generic Visitor class, but not sure about using descendant classes.
Example:
public interface Interface_Test_Case
{
void execute();
void accept(Interface_Test_Visitor v);
}
public interface Interface_Test_Visitor
{
void visit(Interface_Test_Case tc);
}
public interface Interface_Read_Test_Case
: Interface_Test_Case
{
uint read_value();
}
public class USB_Read_Test
: Interface_Read_Test_Case
{
void execute()
{ Console.WriteLine("Executing USB Read Test Case."); }
void accept(Interface_Test_Visitor v)
{ Console.WriteLine("Accepting visitor."); }
uint read_value()
{
Console.WriteLine("Reading value from USB");
return 0;
}
}
public class USB_Read_Visitor
: Interface_Test_Visitor
{
void visit(Interface_Test_Case tc)
{ Console.WriteLine("Not supported Test Case."); }
void visit(Interface_Read_Test_Case rtc)
{ Console.WriteLine("Not supported Read Test Case."); }
void visit(USB_Read_Test urt)
{ Console.WriteLine("Yay, visiting USB Read Test case."); }
}
// Code fragment
USB_Read_Test test_case;
USB_Read_Visitor visitor;
test_case.accept(visitor);
What are the rules the C# compiler uses to determine which of the methods in USB_Read_Visitor will be executed by the code fragment?
I'm trying to factor out dependencies of my testing component. Unfortunately, my current Visitor class contains visit methods for classes not related to the testing component. Am I trying to achieve the impossible?
Since your accept() method doesn't actually call any of the visit() methods, none. :)
However if you invoked it as:
void accept(Interface_Test_Visitor v)
{
Console.WriteLine("Accepting visitor.");
v.Visit(this); // lets invoke it this time
}
the compiler will see that this is first as an instance of USB_Read_Test, then Interface_Read_Test_Case, then Interface_Test_Case. It will choose the most direct overload first (or one where implicit conversions can be used) then go down the inheritance chain until it finds a suitable type that fits an overload. So in this case, it will call visit(USB_Read_Test). You can override this behavior by casting:
v.Visit((Interface_Read_Test_Case)this); // argument is an instance of Interface_Read_Test_Case
v.Visit((Interface_Test_Case)this); // argument is an instance of Interface_Test_Case
If however your class implements multiple interfaces, where each interface has an overload but there is none for the class, you will get ambiguity errors which you will have to resolve.
e.g.,
interface IX { }
interface IY { }
class Class : IX, IY { }
void Call(IX _) { }
void Call(IY _) { }
// no Call(Class _) method
var c = new Class();
Call(c); // error: ambiguous call
Call((IX)c); // not ambiguous
For more information, see Method resolution order and slightly related C#: Passing null to overloaded method - which method is called?.
Instead of defining an entire interface and associated implementations for Visiting, define a Visit method that accepts an Action (or Predicate, or Func depending on what you want the Visitor to do).
class TestCase
{
public void Visit(Action<T> action, T val)
{
action(val);
}
}
var tc = new TestCase();
uint some_val = 3;
tc.Visit((Action) (val) => Console.WriteLine("Val " + val));
Though I'm not entirely clear on what you're trying to do, defining a method that takes a Function can remove the necessity of defining all those interfaces.
As the comment says, accept doesnt invoke any visit methods, so I answer based on what i think you meant...
I would have thought it based on the declared type of the object passed in as a parameter?
USB_Read_Test obj1 = new USB_Read_Test();
Interface_Read_Test_Case obj2 = new USB_Read_Test();
invoking with both as parameters should result in visit(USB_Read_Test urt) for obj1, and visit(Interface_Read_Test_Case rtc) for obj2.
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance. Obviously something else is going on.
The attached NUnit test case shows my problem: Using a dynamic type I can use a method only available in the concrete subclass, but I cannot do the same using a cast (results in InvalidCastException). I'd rather do the casting since this gives me full code completion in VS.
Can anyone explain what's happening and/or give me a hint how I could get code completion in my case without having to reimplement the WorkWithAndCreate-method in every concrete subclass?
cheers, Johannes
using System;
using NUnit.Framework;
namespace SlidesCode.TestDataBuilder
{
[TestFixture]
public class MyTest
{
[Test]
public void DynamicWorks()
{
string aString = CreateDynamic(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateDynamic(Action<dynamic> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
[Test]
public void CastingDoesNotWorkButThrowsInvalidCastException()
{
string aString = CreateWithCast(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate((Action<MyGenericClass<string>>) action);
}
}
internal abstract class MyGenericClass<T>
{
public abstract T Create();
public T WorkWithAndCreate(Action<MyGenericClass<T>> action)
{
action(this);
return this.Create();
}
}
internal class MyConcreteClass : MyGenericClass<string>
{
public override string Create()
{
return "a string";
}
public void OnlyInConcreteClass()
{
}
}
}
Here's the formatted real world example from my comment:
Customer customer = ACustomer(cust =>
{
cust.With(new Id(54321));
cust.With(AnAddress(addr => addr.WithZipCode(22222)));
});
private static Address AnAddress(Action<AddressBuilder> buildingAction)
{
return new AddressBuilder().BuildFrom(buildingAction);
}
private static Customer ACustomer(Action<CustomerBuilder> buildingAction)
{
return new CustomerBuilder().BuildFrom(buildingAction);
}
Some details are missing from it but I hope it makes the purpose clear.
The reason dynamic works is that dynamic does not depend on compile time knowledge of the object types. MyGenericClass<string> does not have the method OnlyInConcreteClass(), but the instance you are passing of course does have the method and dynamic finds this.
By the way, you can make WorkWithAndCreate work like this:
public T WorkWithAndCreate<T1>(Action<T1> action)
where T1 : MyGenericClass<T>
{
action((T1)this);
return this.Create();
}
Then, the call will work too:
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
You now don't have to cast it anymore.
And concerning your builder, would the following work?
private static TResult AnInstance<TBuilder, TResult>(Action<TBuilder> buildingAction)
where TBuilder : Builder<TResult>, new()
{
return new TBuilder().BuildFrom(buildingAction);
}
This is an example of how to use dynamic:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
You said:
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance
Actually, it uses reflections to look up the methods, properties, and fields you invoke by name, at runtime. No casting is done, unless you actually cast the object back to its underlying type.
As for your actual problem, can you give a more concrete example? There may be a better design, but you haven't told us what you're trying to do - just what you're currently doing.
Hazarding a guess, you may want to use a base interface, and make all your functions accept that base interface. Then put the methods you want to call on that interface, and implement them in your concrete types. Usually dynamic is used as a work around when you don't have a base type, or can't modify the base type to add virtual or abstract methods.
If you really want to get this working, as-is, you must write it with a generic type parameter, not a dynamic type parameter. See Pieter's solution for how to do this properly.