A challenge with a colleague about if there is any way to cast a struct to a class here the example that we have tried
namespace ConsoleApplication22
{
class Program
{
static void Main(string[] args)
{
IFoo fooS = new FooStruct();
fooS.Val = 5;
FooClass foo =(FooClass) fooS;
}
}
public interface IFoo
{
int Val { get; set; }
}
public struct FooStruct : IFoo
{
public int Val { get; set; }
}
public class FooClass : IFoo
{
//public FooClass(int val)
//{
//}
private int val;
public int Val
{
get { return val; }
set { val = value; }
}
}
}
but we got an invalid cast exception :D
are there any tricky way to extract the interface and assign it to the class given that an interface is a reference type and a class is a reference type and the class implements the interface
You cannot directly cast between the two via the interface, it isn't allowed because they are not related to each other directly (ie, inheritance).
The compiler can catch a lot of this type of thing and not even allow the cast to compile. If the compiler cannot do it, the runtime does it. For explicit casting, the runtime will throw an exception on failed casts, for attempts at implicit casting (reference types only) the runtime returns null and does not throw an exception.
The type checking actually checks that FooStruct is a FooClass, which it can't be.
However, you can use the casting operators to convert between them making it look like a cast
class Program
{
static void Main(string[] args)
{
FooStruct f = new FooStruct();
f.Val = 2;
FooClass f2 = (FooClass)f;
Console.Read();
}
}
class FooClass : IFoo
{
public static explicit operator FooClass(FooStruct f)
{
FooClass foo = new FooClass();
foo.Val = f.Val;
return foo;
}
public int Val { get; set; }
}
struct FooStruct : IFoo
{
public int Val { get; set; }
public static explicit operator FooStruct(FooClass f)
{
FooStruct foo = new FooStruct();
foo.Val = f.Val;
return foo;
}
}
// This interface has little use in this scenario.
interface IFoo
{
int Val { get; set; }
}
Don't confuse casting with conversion. Also, be wary of applying interfaces to struct types because boxing can occur.
No.
Create a copy method to your FooClass that takes instance of IFoo, and perform necessary copy there.
The most hackish way I could think of (and one you should never, ever use!) is through the use of the Marshal:
public unsafe static TDest UnsafeCast<TDest, TSrc>(object source)
{
byte[] buffer = new byte[Marshal.SizeOf(typeof(TSrc))];
fixed (byte* b = buffer)
Marshal.StructureToPtr(source, new IntPtr(b), true);
fixed (byte* b = buffer)
return (TDest) Marshal.PtrToStructure(new IntPtr(b), typeof (TDest));
}
This literally marshals the data kept in FooClass to FooStruct, which allows it to be "cast" from a reference type to a value type.
You could optionally skip the second marshal if you use the FooStruct type rather than a generic type parameter, by casting the buffer to the FooStruct type from the buffer directly:
fixed (byte* b = buffer)
{
var s = (FooStruct*) b;
return *s;
}
Requires unsafe compiler option, and should never ever be done in any sort of production environment - it's very slow and unpredictable.
Related
imagine a generic class B
public class B<T> : IB
{
public void Foo(object parameter)
{
var param = (T)parameter;
//...
}
}
And a class A, which get's a collection of Bs passed through it's constructor. Notice im using the interface IB as type there.
public class A
{
public A(IEnumerable<IB> collectionOfBs) {}
}
Sometime later, I want to execute some Method on class A, let's say foo, which will take a collection of objects of type T, where T is the generic type of the instance of B passed in the constructor. so these types have to match.
public void foo(IEnumerable<object> param)
{
for (int i = 0; i < collectionOfBs.Count(); i++)
{
collectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
Right now im passing an IEnumerable<object> and cast to type T inside of foo, that will work but I'm wondering if I could have this type check at compile time instead?
Any Ideas if thats possible or not?
Thanks
You can try this using a generic method for the type of the provided parameter.
It does not ensure that TParam and T are same, since you have a non generic interface, but is it the best you can do, as I know, according to a first study of your problem...
Because there is no diamond operator in C# to allow true generic polymorphism on open types.
public interface IB
{
void Foo<TParam>(TParam parameter);
}
public class B<T> : IB
{
public void Foo<TParam>(TParam parameter)
{
var param = parameter;
Console.WriteLine("param type: " + param.GetType().Name);
}
}
public class A
{
private IEnumerable<IB> CollectionOfBs;
public A(IEnumerable<IB> collectionOfBs)
{
CollectionOfBs = collectionOfBs;
}
public void Foo(IEnumerable<object> param)
{
if ( param.Count() < CollectionOfBs.Count() )
throw new ArgumentException();
for ( int i = 0; i < CollectionOfBs.Count(); i++ )
CollectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
Test method
static void Test()
{
var listInstances = new List<IB> { new B<int>(), new B<double>(), new B<string>() };
var container = new A(listInstances);
var listParams = new List<object> { 2, 4.3, "test" };
container.Foo(listParams);
}
Output
param type: Int32
param type: Double
param type: String
Considerations
The problem here is that any bad matching parameter type can be passed.
For example with the Test(), you can have a double instead of the first integer and it works: you get a Double on your Int32 instance...
param type: Double
param type: Double
param type: String
Having the diamond operator <> you will be able to use a generic interface and parse on a closed constructed types list... and your design will have a better smell:
public interface IB<T>
{
void Foo(T parameter);
}
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
Console.WriteLine("param type: " + param.GetType().Name);
}
}
public class A
{
private IEnumerable<IB<>> CollectionOfBs;
public A(IEnumerable<IB<>> collectionOfBs)
{
CollectionOfBs = collectionOfBs;
}
public void Foo(IEnumerable<object> param)
{
if ( param.Count() < CollectionOfBs.Count() )
throw new ArgumentException();
for ( int i = 0; i < CollectionOfBs.Count(); i++ )
{
CollectionOfBs.ElementAt(i).Foo(param.ElementAt(i));
}
}
}
Hence with that, any bad matching type of parameter will raise an exception at runtime.
When you want consistent generic type checking, you need to apply generics consistently. Currently, you are using a half-way approach: B<T> is generic, but IB is not. Then you have a non-generic class A, which couples to the non-generic interface IB, but you want compile-time type checking of T, which both, A and IB know nothing about (only to internally cast it to T). That's a bit of a problem.
From the usage of your classes/interface it seems obvious that you don't expect mixed IB implementations in A, so what you can do is to consistently apply the generic type parameter T on all types:
public class B<T> : IB<T>
{
public void Foo(T parameter)
{
var param = parameter;
//...
}
}
public class A<T>
{
public A(IEnumerable<IB<T>> collectionOfBs) {}
public void foo(IEnumerable<T> param)
{
collectionOfBs.Zip(param, (b, t) => { b.Foo(t); return 0 });
}
}
Note that I replaced your approach with for and ElementAt by Enumerable.Zip.
I'm writing an abstract wrapper for enum in C # (I want something like enum in Vala). My code is:
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator T(TE value)
{
return new T() { Value = value };
}
public static implicit operator TE(T value)
{
return value.Value;
}
}
I want to do with something like this:
public enum EFoo { A, B, C, D, E};
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get { return Value == EFoo.A || Value == EFoo.E; }
}
}
...
Foo foo = EFoo.A;
bool bla = foo.IsBla;
But the code does not compile because C # does not allow both generic parameter,. When compile reports an error:
User-defined conversion must convert to or from the enclosing type
On line
public static implicit operator T(TE value)
Is there any work around or in C# is not so simple?
The implicit operator must convert either from or to the class you are defining it in. Since you are trying to define it in the abstract base class, it can only convert from or to that class.
The line Foo foo = EFoo.A; does not work because you can't define that conversion in your abstract class, you can only define it in your Foo class.
If you changed your code, as I did below, to convert from/to the base class, the implicit conversions work but you don't get the result you want. Wraper<Foo,EFoo> foo2 = EFoo.A; works because it can be defined in the base class.
Your best bet is probably to use the initializer syntax when creating your foo Foo foo = new Foo { Value = EFoo.A }; or to create some generic conversion functions.
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator TE(Wraper<T, TE> value)
{
return value.Value;
}
public static implicit operator Wraper<T, TE>(TE value)
{
return new T { Value = value };
}
}
public enum EFoo
{
A,
B,
C,
D,
E
}
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get
{
return Value == EFoo.A || Value == EFoo.E;
}
}
}
I'm trying to wrap a type (outside of my control) so that it would seamlessly appear to implement an interface (also outside of my control).
Given these defintions
// External types. Not changable.
class Foo {
public int I { get; set; }
public int J { get; set; }
}
interface IGenerateSignature {
string Generate();
}
I would like to use a Foo instance to call a method with an IGenerateSignature parameter:
void Test() {
var foo = new Foo { I = 1, J = 2 };
GetSignature(foo);
}
void GetSignature(IGenerateSignature sig) {
Console.Write(sig.Generate());
}
I tried creating an intermediary struct like this:
struct FooSignaturizer : IGenerateSignature {
private readonly Foo _foo;
public FooSignaturizer(Foo f) {
_foo = f;
}
public static implicit operator FooSignaturizer(Foo f) {
return new FooSignaturizer(f);
}
public string Generate() {
return _foo.I + ":" + _foo.J;
}
}
But for some reason overload resolution fails to find the conversion from Foo to FooSignaturizer, and I get a "Cannot convert" compiler error. If I manually add a cast, GetSignature((FooSignaturizer) foo), it works. However, I need to also add support for the Bar and Qux types, with BarSignaturizer and QuxSignaturizer, so the cast won't work for those cases.
Is there a way to accomplish this?
As per 7.5.3.1 of the C# spec, only implicit conversions from argument expression to parameter type are considered.
7.5.3.1 Applicable function member
A function member is said to be an applicable function member with respect to an argument list A when all of the following are true:
Each argument in A corresponds to a parameter in the function member declaration as described in §7.5.1.1, and any parameter to which no argument corresponds is an optional parameter.
For each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is identical to the parameter passing mode of the corresponding parameter, and
for a value parameter or a parameter array, an implicit conversion (§6.1) exists from the argument to the type of the corresponding parameter, or
for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. After all, a ref or out parameter is an alias for the argument passed.
What you have here isn't an implicit conversion from Foo to IGenereateSignature, it's a wrapper.
As an explanation for this behaviour, you can't exect the compiler to go though every implementation of IGenerateSignature in scope to see whether it has an implicit conversion to/from Foo. What if there was more than one?
In terms of how you can achieve this for Foo, Bar and Qux...
What you're trying to achieve, one call to GetSignature(fooOrBarOrQux), isn't possible, because (based on your description of Foo) you can't have one variable that can be a Foo or a Bar or a Qux at compile time - they're unrelated. You'll always need three call sites, so there's no reason not to have three slightly-different conversions (wrapper class or overloaded method call or something) for the three cases.
... unless you use dynamic?
Rawling's answer gives a good explanation of why you have the problem. Since you can't fix this with implicit conversion, you could try extension methods to convert all types to IGenerateSignature like this:
void Test() {
var foo = new Foo { I = 1, J = 2 };
GetSignature(foo.AsIGenerateSignature());
}
void GetSignature(IGenerateSignature sig) {
Console.Write(sig.Generate());
}
public static class GenerateSignatureExtensions
{
public static IGenerateSignature AsIGenerateSignature(this IGenerateSignature me)
{
return me;
}
public static IGenerateSignature AsIGenerateSignature(this Foo me)
{
return new FooSignaturizer(me);
}
public static IGenerateSignature AsIGenerateSignature(this Bar me)
{
return new BarSignaturizer(me);
}
//....
}
Rawling's answer gives a great explanation of the why you are having a problem. As to how to achieve what you want. I might consider something like this:
public interface ISignaturizer
{
IGenerateSignature ToSignaturizer();
}
struct FooSignaturizer : IGenerateSignature, ISignaturizer{
private readonly Foo _foo;
public FooSignaturizer(Foo f) {
_foo = f;
}
public string Generate() {
return _foo.I + ":" + _foo.J;
}
public IGenerateSignature ToSignaturizer()
{
return (IGenerateSignature)this;
}
}
Now BarSignaturizer and QuxSignaturizer can implement the same interface. And then you can do:
GetSignature(((ISignaturizer)fooOrBarOrQux).ToSignaturizer());
Which isn't quite as elegant, but I think should accomplish what you need.
I have an explicit conversion defined from type Bar to type Foo.
public class Bar
{
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
However, when I do:
using System.Linq;
...
var manyFoos = manyBars.Cast<Foo>();
It throws an exception saying it can't cast.
How do I tell Cast to use my cast operator to try the conversion?
Cast operators are static methods that the compiler calls when you use casts in code. They cannot be used dynamically. Enumerable.Cast does a runtime cast of two unconstrained generic types, so it cannot know during compile time which cast operators to use. To do what you want, you can use Select:
manyFoos.Select(foo => (Bar)foo);
The linq Cast method essentially does a box and unbox. It is not aware of either implicit or explicit cast operators defined in C#, which the compiler treats standard method calls.
You'd have to do something like this:
var manyFoos = manyBars.Select(bar => (Foo)bar);
As all other answers pointed type is not known in compile time since Cast method is not generic. It holds type of object and makes a explicit cast to T. this fails because you don't have conversion operator from object to Foo. And that is not possible also.
Here is a work around using dynamics in which cast will be done in runtime.
public static class DynamicEnumerable
{
public static IEnumerable<T> DynamicCast<T>(this IEnumerable source)
{
foreach (dynamic current in source)
{
yield return (T)(current);
}
}
}
Then use it like
var result = bars.DynamicCast<Foo>();//this works
Use Select:
var manyFoos = manyBars.Select(bar => (Foo)bar);
Your code doesn't actually compile. I assume that there is a property "Gar" in the "Bar" class as well?
public class Bar
{
public string Gar { get; set; }
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
static void Main(string[] args)
{
List<Bar> bars = new List<Bar>();
for (int i = 0; i < 10; i++)
bars.Add(new Bar() { Gar = i.ToString() });
var result = bars.Cast<Foo>();
}
+
I encaurage you to read about covariance.
Assuming A is convertible to B, X is covariant if X<A> is convertible to X<B>.
With C#’s notion of covariance (and contravariance), “convertible” means convertible via an implicit reference conversion— such as A subclassing B, or A implementing B. Numeric conversions, boxing conversions, and custom conversions are not included.
You have to do that with interfaces.
I have the following class and extension class (for this example):
public class Person<T>
{
public T Value { get; set; }
}
public static class PersonExt
{
public static void Process<TResult>(this Person<IEnumerable<TResult>> p)
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
}
I was expecting I could write something like the following and it would work, but it doesn't:
var x = new Person<List<String>>();
x.Process();
Since List is lower in the inheritance tree than IEnumerable, shouldn't this be valid? It works if I new up a Person<IEnumerable<String>> of course because that's the direct type.
I'm trying to use an extension method that can be applied to all Person<T>'s as long as T implements IEnumerable<Something> because I need to use the .Any() method.
EDIT: Maybe my understanding of covariance is off? I know IEnumerable<String> should convert to IEnumerable<Object>, but couldn't IList<String> convert to IEnumerable<String>?
EDIT2: Forgot to mention that I am using .net 4.0.
I know IEnumerable<String> should
convert to IEnumerable<Object>, but
couldn't IList<String> convert to
IEnumerable<String>?
IList<String> can convert to IEnumerable<String>. The problem is that you're trying to convert Person<List<String>> to Person<IEnumerable<String>>, which is illegal. For example, it's perfectly valid to write:
var x = new Person<IEnumerable<String>>();
x.Value = new string[0];
since Value is of type IEnumerable<String> and a string array is an IEnumerable<String>. However, you cannot write:
var x = new Person<List<String>>();
x.Value = new string[0];
since Value is of type List<String>. Since you can't use a Person<List<String>> in all places where you could use a Person<IEnumerable<String>>, it's not a legal cast.
Note that you can do something similar to what you want if you add a second type parameter to your extension method:
public static void Process<TResult, TList>(this Person<TList> p)
where TList : IEnumerable<TResult>
{
Console.WriteLine(p.Value.Any());
}
Unfortunately, the compiler won't be able to infer both type parameters, so you would have to call it like this:
var x = new Person<List<String>>();
x.Process<String, List<String>>();
If you are using C# 4.0 and can use covariance, then you can define a covariant interface for person:
public interface IPerson<out T>
{
T Value { get; }
}
public class Person<T>
: IPerson<T>
{
public T Value { get; set; }
}
And then write your extension method as:
public static void Process<TResult>(this IPerson<IEnumerable<TResult>> p)
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
Since IPerson<T>.Value is read-only, a IPerson<List<String>> can be used everywhere that an IPerson<IEnumerable<String>> can be, and the conversion is valid.
I'm not sure you've quite grasped the correct use of generics. In any event ...
The only thing that is incorrect is your declaration of extension method, and the way you are attempting to constrain the extension method.
public static class ThingExtensions
{
public static void Process<T>(this Thing<T> p)
where T : IEnumerable<string>
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
}
All I've really done is rename Person to Thing so that we're not getting hung up on what a Person<List<string>> really is.
public class Thing<T>
{
public T Value { get; set; }
}
class ListOfString : List<string>
{ }
class Program
{
static void Main(string[] args)
{
var x = new Thing<ListOfString>();
x.Value = new ListOfString();
x.Process();
x.Value.Add("asd");
x.Process();
var x2 = new Thing<int>();
// Error 1 The type 'int' cannot be used as type parameter 'T'
// in the generic type or method
// 'ThingExtensions.Process<T>(Thing<T>)'.
// There is no boxing conversion from 'int' to
// 'System.Collections.Generic.IEnumerable<string>'.
//x2.Process();
Console.Read();
}
}
You could also move the generic constraint to the Thing<T> if that was more applicable.
You mention covariance, but don't actually use it. You have to specify in or out on your generic parameters. Note that co/contravariance doesn't work on class types; they must be applied to interfaces.
So, introducing an interface and making it covariant:
public interface IPerson<out T>
{
T Value { get; }
}
public class Person<T> : IPerson<T>
{
public T Value { get; set; }
}
public static class PersonExt
{
public static void Process<TResult>(this IPerson<IEnumerable<TResult>> p)
{
// Do something with .Any().
Console.WriteLine(p.Value.Any());
}
}
allows this code to compile:
var x = new Person<List<String>>();
x.Process();