Related
So I have this test program:
namespace ConsoleApplication1TEST{
class Program
{
static void Main(string[] args)
{
new derp<int,int>(5,4);
}
}
class derp<T,V>
{
public T top;
public V vop;
public derp(T to, V vo)
{
top = to;
vop = vo;
top.ToString();
}
}
}
top.ToString is allowed. As are GetHashCode, GetType, and Equals. However, ToUpper is not allowed, and neither are other string-specific methods. Can this be changed?
When I place a method that is not allowed, this is the error I get:
Error 1 'ConnectionServiceT' does not contain a definition for
'connect' and no extension method 'connect' accepting a first argument
of type 'ConnectionServiceT' could be found (are you missing a using
directive or an assembly reference?)
top.ToString is allowed. GetHashCode, GetType, Equals is also allowed.
However, ToUpper is not allowed, and other string-specific methods are not allowed. Can this be changed?
That's perfectly normal. The compiler knows nothing about the actual type of T, so it can't assume that it has a ToUpper method. However, since all types (except pointers) inherit from Object, calling methods of the Object class is allowed.
Now, if there was a constraint on T to force it to inherit a type that has a ToUpper method, your code would work:
class derp<T,V> where T : String
It's a bad example, because String is sealed, so this code wouldn't compile, but it's just to illustrate the idea.
Anyway, if you want to be able to call the String.ToUpper method on top, then the type of top cannot be generic: it has to be String.
To learn more about generic constraints, see MSDN: http://msdn.microsoft.com/en-us/library/d5x73970.aspx
It is reasonable that the method ToUpper() is not allowed, since this is a method specific for string types. If your type isn't a string then you can't use the ToUpper() method, because this method is specific to string types.
On the other hand, since all types inherrit the object type, they inherit it's methods, which are ToString(), GetHashCode(), GetType() and Equals().
This is a good link regarding the inheritance in C#, in where you can see more thoroughly what I am talking about.
Also here is stated that:
In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.
.ToString() works on every type. If the type is not a string the type's name will be returned.
.ToUpper() is a string specific, won't work on types other than string.
Can this be changed?
You don't know what T and V are, so the only assumption the compiler can make is that they inherit from object, which is why ToString, GetHashCode, GetType, and Equals are allowed (since they're methods on object which every class inherits from).
If ConnectionServiceT (and other similar classes) inherit from a base class you can constrain T and V to be subclasses of a given type:
class derp<T,V> where T:BaseService
where V:MyOtherClass
{
public T top;
public V vop;
public derp(T to, V vo)
{
top = to;
vop = vo;
top.ToString();
}
}
Then you can call methods specific to BaseService on instances of T (since you know that T must derive from BaseService.
But you can't constrain to string because it's sealed - the only possible class would be derp<string, string> so there's no reason to use generics.
It is a good thing you cant use ToUpper(). You are sending in integers, those certainly do not have a ToUpper method. ToUpper is a method that belongs to string objects. You could do this:
string myUpperCaseString = top.ToString().ToUpper();
//or
if(top.GetType() == typeof(string)
{
string myUpperCaseString = (top as string).ToUpper();
}
What you may have been mistaken about, is that ToString() does not change the string... it instead returns a new string representation of that object, you then have to store this object somewhere. Above I stored it in a variable called myUpperCaseString with the type of string.
ToString, GetHashCode, GetType are all methods that belong to the object class and anything that inherits from it.
I was looking at this question, and aside from a rather odd way to enumerate something, the op was having trouble because the enumerator is a struct. I understand that returning or passing a struct around uses a copy because it is a value type:
public MyStruct GetThingButActuallyJustCopyOfIt()
{
return this.myStructField;
}
or
public void PretendToDoSomething(MyStruct thingy)
{
thingy.desc = "this doesn't work as expected";
}
So my question is if MyStruct implements IMyInterface (such as IEnumerable), will these types of methods work as expected?
public struct MyStruct : IMyInterface { ... }
//will caller be able to modify the property of the returned IMyInterface?
public IMyInterface ActuallyStruct() { return (IMyInterface)this.myStruct; }
//will the interface you pass in get its value changed?
public void SetInterfaceProp(IMyInterface thingy)
{
thingy.desc = "the implementing type is a struct";
}
Yes, that code will work, but it needs explanation, because there is a whole world of code that will not work, and you're likely to trip into that unless you know this.
Before I forget: Mutable structs are evil. OK, with that out of the way, let's move on.
Let's take a simple example, you can use LINQPad to verify this code:
void Main()
{
var s = new MyStruct();
Test(s);
Debug.WriteLine(s.Description);
}
public void Test(IMyInterface i)
{
i.Description = "Test";
}
public interface IMyInterface
{
string Description { get; set; }
}
public struct MyStruct : IMyInterface
{
public string Description { get; set; }
}
When executing this, what will be printed?
null
OK, so why?
Well, the problem is this line:
Test(s);
This will in fact box that struct and pass the boxed copy to the method. You're successfully modifying that boxed copy, but not the original s variable, which was never assigned anything, and is thus still null.
OK, so if we change just one line in the first piece of code:
IMyInterface s = new MyStruct();
Does this change the outcome?
Yes, because now you're boxing that struct here, and always use the boxed copy. In this context it behaves like an object, you're modifying the boxed copy and writing out the contents of the boxed copy.
The problem thus crops up whenever you box or unbox that struct, then you get copies that live separate lives.
Conclusion: Mutable structs are evil.
I see two answers about using ref here now, and this is barking up the wrong tree. Using ref means you've solved the problem before you added ref.
Here's an example.
If we change the Test method above to take a ref parameter:
public void Test(ref IMyInterface i)
Would this change anything?
No, because this code is now invalid:
var s = new MyStruct();
Test(ref s);
You'll get this:
The best overloaded method match for 'UserQuery.Test(ref UserQuery.IMyInterface)' has some invalid arguments
Argument 1: cannot convert from 'ref UserQuery.MyStruct' to 'ref UserQuery.IMyInterface'
And so you change the code to this:
IMyInterface s = new MyStruct();
Test(ref s);
But now you're back to my example, just having added ref, which I showed is not necessary for the change to propagate back.
So using ref is orthogonal, it solves different problems, but not this one.
OK, more comments regarding ref.
Yes, of course passing a struct around using ref will indeed make the changes flow throughout the program.
That is not what this question was about. The question posted some code, asked if it would work, and it would. In this particular variant of code it would work. But it's so easy to trip up. And pay particular note that the question was regarding structs and interfaces. If you leave interfaces out of it, and pass the struct around using ref, then what do you have? A different question.
Adding ref does not change this question, nor the answer.
Within the CLR, every value-type definition actually defines two kinds of things: a structure type, and a heap object type. A widening conversion exists from the structure type to the boxed object type, and a narrowing conversion exists from Object to the structure type. The structure type will behave with value semantics, and the heap object type will behave with mutable reference semantics. Note that the heap object types associated with all non-trivial structure types [i.e. those with any non-default states] are always mutable, and nothing in the structure definition can cause them to be otherwise.
Note that value types may be constrained, cast, or coerced to interface types, and cast or coerced to reference types. Consider:
void DoSomethingWithDisposable<T,U>(ref T p1,
List<int>.Enumerator p2) where T:IDisposable
{
IDisposable v1a = p1; // Coerced
Object v1b = p1; // Coerced
IDisposable v2a = (IDisposable)p2; // Cast
Object v2b = (Object)p2; // Cast
p1.Dispose(); // Constrained call
}
void blah( List<string>.Enumerator p1, List<int>.Enumerator p2) // These are value types
{
DoSomethingWithDisposable(p1,p2); // Constrains p1 to IDisposable
}
Constraining a generic type to an interface type does not affect its behavior as a value type. Casting or coercing an a value type to an interface or reference type, however, will create a new instance of the heap object type and return a reference to that. That reference will then behave with reference-type semantics.
The behavior of value types with generic constraints can at times be very useful, and such usefulness can apply even when using mutating interfaces, but unfortunately there's no way to tell the compiler that a value type must remain as a value type, and that the compiler should warn if it would find itself converting it to something else. Consider the following three methods:
bool AdvanceIntEnumerator1(IEnumerator<int> it)
{ return it.MoveNext(); }
bool AdvanceIntEnumerator2(ref T it) where T:IEnumerator<int>
{ return it.MoveNext(); }
bool AdvanceIntEnumeratorTwice<T>(ref T it) where T:IEnumerator<int>
{ return it.MoveNext() && AdvanceIntEnumerator1(it); }
If one passes to the first piece of code a variable of type List<int>.Enumerator, the system will copy its state to a new heap object, call MoveNext on that object, and abandon it. If one passes instead a variable of type IEnumerator<int> which holds a reference to a heap object of type List<int>.Enumerator, it will call MoveNext on that instance, which the calling code will still retain.
If one passes to the second piece of code a variable of type List<int>.Enumerator, the system will call MoveNext on that variable, thus changing its state. If one passes a variable of type IEnumerable<T>, the system will call MoveNext on the object referred to by that variable; the variable won't be modified (it will still point to the same instance), but the instance to which it points will be.
Passing to the third piece of code a variable of type List<int>.Enumerator will cause MoveNext to be called on that variable, thus changing its state. If that returns true, the system will copy the already-modified variable to a new heap object and call MoveNext on that. The object will then be abandoned, so the variable will only be advanced once, but the return value will indicate whether a second MoveNext would have succeeded. Passing the third piece of code a variable of type IEnumerator<T> which holds a reference to a List<T>.Enumerator, however, will cause that instance to be advanced twice.
No, interface is a contract, to make it work properly you need to use ref keyword.
public void SetInterfaceProp(ref IMyInterface thingy)
{
thingy.desc = "the implementing type is a struct";
}
What matters here is a real type that stays inside that interface wrap.
To be more clear:
even if code with method SetInterfaceProp defined like
public void SetInterfaceProp(IMyInterface thingy)
{
thingy.desc = "the implementing type is a struct";
}
will work:
IMyInterface inter= default(MyStruct);
SetInterfaceProp(inter);
this one will not :
MyStruct inter = default(MyStruct);
SetInterfaceProp(inter);
You can not gurantee that the caller of your method will always use IMyInterface, so to guarantee expected behavior, in this case, you can define ref keyword, that will guarantee that in both cases method would run as expected.
I created an Class which is only able to handle primitive (or ICloneable) Types
I want to know if it's possible to say something like:
public myobject(primitiv original){...}
or do I really need to create a constructor for each primitive type like:
public myobject(int original){...}
public myobject(bool original){...}
...
What I am trying to achieve is to create an object with 3 public properties Value, Original and IsDirty.
The Value will be an deep Clone of Original so the Original needs to be primitve or ICloneable
Primitive types in C# are defined as structs (implemented generally as ValueType in the .NET CLR). I believe you have two options:
As has been said already: Receive any type, check it against every acceptable type, throw an exception if it doesn't match.
Make your class generic, make the constructor generic with a constraint of where T : struct (with T being the type parameter). This will catch all structs, not just the primitive types, but I think that's the best you can hope for without manual checking and with compile-time checking. You can mix this constraint with other ones, of course.
And you can combine the two options above to have some of the checking be done at compile-time and some of it be done at run-time.
If you want to do that to force whomever is using your API to use such types (through compile time errors should they use the wrong types), I'm afraid it can't be done.
You could, however, receive an object in the constructor, evaluate its type, and throw an ArgumentException in case the parameter is neither one of the "primitive" types nor implements ICloneable.
Edit: This might be useful. You can determine whether a variable belongs to a primitive type with the following code:
Type t = foo.GetType();
t.IsPrimitive; // so you don't have to do an evaluation for each primitive type.
It is not exactly what you asked, but you can have 2 constructors, one for structs and one for ICloneable:
public myobject(System.ValueType original){...}
public myobject(ICloneable original){...}
How about generics instead of reflection?
public class MyObject<T>
where T: IComparable
{
public MyObject(T original)
{
// do runtime check
}
}
var c1 = new MyObject<int>(1);
// or
var c2 = new MyObject<Int32>(2);
I recently came across this Stackoverflow question: When to use struct?
In it, it had an answer that said something a bit profound:
In addition, realize that when a struct implements an interface - as
Enumerator does - and is cast to that implemented type, the struct
becomes a reference type and is moved to the heap. Internal to the
Dictionary class, Enumerator is still a value type. However, as soon
as a method calls GetEnumerator(), a reference-type IEnumerator is
returned.
Exactly what does this mean?
If I had something like
struct Foo : IFoo
{
public int Foobar;
}
class Bar
{
public IFoo Biz{get; set;} //assume this is Foo
}
...
var b=new Bar();
var f=b.Biz;
f.Foobar=123; //What would happen here
b.Biz.Foobar=567; //would this overwrite the above, or would it have no effect?
b.Biz=new Foo(); //and here!?
What exactly are the detailed semantics of a value-type structure being treated like a reference-type?
Every declaration of a structure type really declares two types within the Runtime: a value type, and a heap object type. From the point of view of external code, the heap object type will behave like a class with a fields and methods of the corresponding value type. From the point of view of internal code, the heap type will behave as though it has a field this of the corresponding value type.
Attempting to cast a value type to a reference type (Object, ValueType, Enum, or any interface type) will generate a new instance of its corresponding heap object type, and return a reference to that new instance. The same thing will happen if one attempts to store a value type into a reference-type storage location, or pass it as a reference-type parameter. Once the value has been converted to a heap object, it will behave--from the point of view of external code--as a heap object.
The only situation in which a value type's implementation of an interface may be used without the value type first being converted to a heap object is when it's passed as a generic type parameter which has the interface type as a constraint. In that particular situation, interface members may be used on the value type instance without its having to be converted to a heap object first.
Read about boxing and unboxing (search the internet). For example MSDN: Boxing and Unboxing (C# Programming Guide).
See also the SO thread Why do we need boxing and unboxing in C#?, and the threads linked to that thread.
Note: It is not so important if you "convert" to a base class of the value type, as in
object obj = new Foo(); // boxing
or "convert" to an implemented interface, as in
IFoo iFoo = new Foo(); // boxing
The only base classes a struct has, are System.ValueType and object (including dynamic). The base classes of an enum type are System.Enum, System.ValueType, and object.
A struct can implement any number of interfaces (but it inherits no interfaces from its base classes). An enum type implements IComparable (non-generic version), IFormattable, and IConvertible because the base class System.Enum implements those three.
I'm replying your post about your experiment on 2013-03-04, though I might be a bit late :)
Keep this in mind: Every time you assign a struct value to a variable of an interface type (or return it as an interface type) it will be boxed. Think of it like a new object (the box) will be created on the heap, and the value of the struct will be copied there. That box will be kept until you have a reference on it, just like with any object.
With behavior 1, you have the Biz auto property of type IFoo, so when you set a value here, it will be boxed and the property will keep a reference to the box. Whenever you get the value of the property, the box will be returned. This way, it mostly works as if Foo would be a class, and you get what you expect: you set a value and you get it back.
Now, with behavior 2, you store a struct (field tmp), and your Biz property returns its value as an IFoo. That means every time get_Biz is called, a new box will be created and returned.
Look through the Main method: every time you see a b.Biz, that's a different object (box). That will explain the actual behavior.
E.g. in line
b.Biz.Foobar=567;
b.Biz returns a box on the heap, you set the Foobar in it to 576 and then, as you do not keep a reference to it, it is lost immediatly for your program.
In the next line you writeline b.Biz.Foobar, but this call to b.Biz will then again create a quite new box with Foobar having the default 0 value, that's what printed.
Next line, variable f earlier was also filled by a b.Biz call which created a new box, but you kept a reference for that (f) and set its Foobar to 123, so that's still what you have in that box for the rest of the method.
So, I decided to put this behavior to the test myself. I'll give the "results", but I can't explain why things happen this way. Hopefully someone with more knowledge about how this works can come along and enlighten me with a more thorough answer
Full test program:
using System;
namespace Test
{
interface IFoo
{
int Foobar{get;set;}
}
struct Foo : IFoo
{
public int Foobar{ get; set; }
}
class Bar
{
Foo tmp;
//public IFoo Biz{get;set;}; //behavior #1
public IFoo Biz{ get { return tmp; } set { tmp = (Foo) value; } } //behavior #2
public Bar()
{
Biz=new Foo(){Foobar=0};
}
}
class MainClass
{
public static void Main (string[] args)
{
var b=new Bar();
var f=b.Biz;
f.Foobar=123;
Console.WriteLine(f.Foobar); //123 in both
b.Biz.Foobar=567; /
Console.WriteLine(b.Biz.Foobar); //567 in behavior 1, 0 in 2
Console.WriteLine(f.Foobar); //567 in behavior 1, 123 in 2
b.Biz=new Foo();
b.Biz.Foobar=5;
Console.WriteLine(b.Biz.Foobar); //5 in behavior 1, 0 in 2
Console.WriteLine(f.Foobar); //567 in behavior 1, 123 in 2
}
}
}
As you can see, by manually boxing/unboxing we get extremely different behavior. I don't completely understand either behavior though.
I have a object:
ExampleClass ex = new ExampleClass();
And:
Type TargetType
I would like to cast ex to type described by TargetType like this:
Object o = (TargetType) ex;
But when I do this I get:
The type or namespace name 't' could
not be found
So how to do this? Am I missing something obious here?
Update:
I would like to obtain something like this:
public CustomClass MyClassOuter
{
get
{
return (CustomClass) otherClass;
}
}
private otherClass;
And because I will have many properties like this I would like do this:
public CustomClass MyClassOuter
{
get
{
return (GetThisPropertyType()) otherClass;
}
}
private SomeOtherTypeClass otherClass;
Context:
Normally in my context in my class I need to create many properties. And in every one replace casting to the type of property. It does not seem to have sense to me (in my context) because I know what return type is and I would like to write some kind of code that will do the casting for me. Maybe it's case of generics, I don't know yet.
It's like I can assure in this property that I get the right object and in right type and am 100% able to cast it to the property type.
All I need to do this so that I do not need to specify in every one property that it has to "cast value to CustomClass", I would like to do something like "cast value to the same class as this property is".
For example:
class MYBaseClass
{
protected List<Object> MyInternalObjects;
}
class MyClass
{
public SpecialClass MyVeryOwnSpecialObject
{
get
{
return (SpecialClass) MyInteralObjects["MyVeryOwnSpecialObject"];
}
}
}
And ok - I can make many properties like this one above - but there is 2 problems:
1) I need to specify name of object on MyInternalObjects but it's the same like property name. This I solved with System.Reflection.MethodBase.GetCurrentMethod().Name.
2) In every property I need to cast object from MyInternalObjects to different types. In MyVeryOwnSpecialObject for example - to SpecialClass. It's always the same class as the property.
That's why I would like to do something like this:
class MYBaseClass
{
protected List<Object> MyInternalObjects;
}
class MyClass
{
public SpecialClass MyVeryOwnSpecialObject
{
get
{
return (GetPropertyType()) MyInteralObjects[System.Reflection.MethodBase.GetCurrentMethod().Name];
}
}
}
And now concerns: Ok, what for? Because further in my application I will have all benefits of safe types and so on (intellisense).
Second one: but now you will lost type safety in this place? No. Because I'm very sure that I have object of my type on a list.
Object o = (TargetType) ex;
This code is useless. You might have a type on the right but it's still only an object on the left side. You can't use functionality specific to TargetType like this.
This is how you can invoke a method of an unknown object of a given type:
object myObject = new UnknownType();
Type t = typeof(UnknownType); // myObject.GetType() would also work
MethodInfo sayHelloMethod = t.GetMethod("SayHello");
sayHelloMethod.Invoke(myObject, null);
With this UnknownType class:
class UnknownType
{
public void SayHello()
{
Console.WriteLine("Hello world.");
}
}
Usually a desire to do this indicates a misunderstanding. However, there are very occasionally legitimate reasons to do this. It depends on whether or not it's going to be a reference conversion vs an unboxing or user-defined conversion.
If it's a reference conversion, that means the actual value (the reference) will remain entirely unchanged. All the cast does is perform a check and then copy the value. That has no real use - you can perform the check using Type.IsAssignableFrom instead, and just use the implicit cast to object if you want it in a variable of type object.
The main point of casting is to provide the compiler with more information. Now if you only know the type at execution time, that clearly can't help the compiler.
What do you plan to do with o after you've performed the cast? If you can explain that, we can try to explain how to achieve the effect you're after.
If you really want a user-defined conversion or an unboxing conversion to occur, that could be a different matter - but I suspect that's not the case.
EDIT: Having seen your update, your property is just declared to return CustomClass, so all you need is:
public CustomClass MyClassOuter
{
get
{
return (CustomClass) otherClass;
}
}
I suspect you still haven't really given us all the information we need. Is that definitely how your property will be defined, with CustomClass being a definite type? Why were you trying to perform the cast dynamically when you know the property type?
EDIT: It sounds like you're just trying to save some typing - to make it easier to cut and paste. Don't. You know the type at compile-time, because you know the type of the property at compile-time (it's specified in the code just a few lines above). Use that type directly. Likewise don't try to get the name of the current method to work out the key to use. Just put the name in directly. Again, you know it at compile-time, so why be dynamic? I'm all for laziness when it makes sense, but in this case it just doesn't.
if (ex is ExampleClass)
{
ExampleClass myObject = (ExampleClass)ex;
}
That would do it but I guess the question is what are you trying to achieve and why? I often find that if something seems really, really difficult then I'm probably doing it wrong.
Now it seems to be impossible, but soon will be available with new feature in .NET 4.0 called "dynamic":
http://www.codeguru.com/vb/vbnet30/article.php/c15645__4/
I'm not entirely sure what you're trying to do, but the impression I'm getting is that you'd like to have a single instance of some object which can "act like" many different types of objects, and you want to have getters which will allow you to view this one object in those various different ways very easily. In that case, I would suggest making a single getter method (not a property), like so:
public T Get<T>()
{
return (T)myObject;
}
Then you would call it like so:
Foo foo = box.Get<Foo>();
Bar bar = box.Get<Bar>();
// etc...
Two things to note: this is definitely not type-safe, since you can pass any type for T, including types for which the cast will fail. You can constrain it a little, like so:
public T Get<T>() where T : SomeBaseType
Which will cause a compile error if you try to use a type which is incompatible with SomeBaseType, but I'm not sure that's totally robust. But hopefully this gets you most of the way there.
Is this what you had in mind?