Create dynamic struct with Generic Type - c#

I'm new in .net and C# and I'm trying to create an instance of MyStruct, without known the Type before.
so my class receive 3 type in the constructor and I need to create an Instance of MyStruct with this type.
I looked on internet and saw the last part but I can't compile this.
namespace IQUnionTag
{
public class IQUnionTag
{
private struct MyStruct<A, B, C>
{
public A value1;
public B value2;
public C value3;
}
private object MyStructure;
private Type a;
private Type b;
private Type c;
public IQUnionTag(Type a, Type b, Type c)
{
this.a = a;
this.b = b;
this.c = c;
int d = 2;
var d1 = typeof (MyStruct<>); // Doesn't compile
Type[] typeArgs = { a, b, c };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Console.WriteLine(o);
}
}
}
I just want something like
Mystructure = new MyStruct<a,b,c> // this doesn't compile too
typeof(MyStruct<>) make error compile like
Erreur Using the generic type 'IQUnionTag.IQUnionTag.MyStruct<A,B,C>' requires 3 type arguments
i certainly missed something, can you help me to create my instance?

It is not clear what is your purpose but you can do:
public class IQUnionTag
{
private struct MyStruct<A, B, C>
{
public A value1;
public B value2;
public C value3;
}
private object MyStructure;
private Type a;
private Type b;
private Type c;
public IQUnionTag(Type a, Type b, Type c)
{
this.a = a;
this.b = b;
this.c = c;
int d = 2;
var d1 = typeof(MyStruct<,,>); // this is the way to get type of MyStruct
Type[] typeArgs = { a, b, c };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Console.WriteLine(o);
}
}

Related

How to add multiple constructors to a struct?

I have the following code:
struct test {
public int a;
public int b;
public test(int a) {
this(a, null);
}
public test(int a, int b) {
this.a = a;
this.b = b;
}
}
Where I would like to have two different constructors for the test struct, one where I only need to pass in a and another where I can pass in both a and b.
This code does not work, as it fails with a few errors:
For the public test(int a) { line:
Field 'test.a' must be fully assigned before control is returned to the caller
Field 'test.b' must be fully assigned before control is returned to the caller
And for the this(a, null); line:
Method name expected.
The 'this' object cannot be used before all of its fields have been assigned
struct test {
public int a;
public int b;
public test(int a) : this(a, 0) { }
public test(int a, int b = 0) {
this.a = a;
this.b = b;
}
}
You can't assign null to int. Also your variable names are ambiguous. You can use an optional parameter to achieve what you're looking for. Or chaining constructors.
Try this
struct Test
{
public readonly int a;
public readonly int b;
public Test(int a) : this()
{
this.a = a;
this.b = 0;
}
public Test(int a, int b) : this()
{
this.a = a;
this.b = b;
}
}
an alternative is to use an optional parameter with one constructor
public Test(int a, int b = 0) : this()
{
this.a = a;
this.b = b;
}
or instead of 0 to use default(int), or just default
public Test(int a) : this()
{
this.a = a;
this.b = default(int);
}
The : this() call is added by Microsoft when the create constructor tool is used so I have added it here. I think it is just to remind the reader of the code that space in the stack is allocated first and then the fields are assigned.
I also added the readonly keyword because mutable structures are evil and to emphasize the requirements the fields need to be all defined before the constructor ends.
Or you can always use one constructor from another constructor
public Test(int a) : this(a, 0)
{ }

How to achieve multiple return values in C# like python style

I have a python script:
def f():
a = None
b = None
return (a, b)
a, b = f()
It's so easy to achieve multiple return values in python.
And now I want to achieve the same result in C#. I tried several ways, like return int[] or KeyValuePair. But both ways looked not elegant. I wonder a exciting solution. thanks a lot.
Use Tuple class.
public Tuple<int,int> f()
{
Tuple<int,int> myTuple = new Tuple<int,int>(5,5);
return myTuple;
}
Unfortunately, C# does not support this. The closest you can get is to use out parameters:
void f(out int a, out int b) {
a = 42;
b = 9;
}
int a, b;
f(out a, out b);
You can obviously do
object F(out object b)
{
b = null;
return null
}
object b;
var a = F(out b)
but better to use Tuple with a functional style,
Tuple<object, object> F()
{
return Tuple.Create<object, object>(null, null);
}
var r = F();
var a = r.Item1;
var b = r.Item2;
but, since in c# you can be explicit, why not define your return type.
struct FResult
{
public object A;
public object B;
}
FResult F()
{
return new FResult();
}
var r = F();
var a = F.A;
var b = F.B;
This seems like a small price to pay for the semantic benefits.
This feature is available in C#7 with .Net 4.7.
private (string a, string b) f()
{
return (a: null, b: null);
// or simply: return (null, null);
}
var (a, b) = f();

Super type with flexible functionality

How can I implement this:
I have 3 types (actually Interface): A , B and C
A has no methods, but B and C have some methods.
I want the type A in some situations can be cast to type B and use B methods and in other situation cast to type C and use its methods?
class Program
{
interface A { }
interface B :A { void b(); } // B inherits from A
interface C :A { void c(); } // C also inherits from A
static void Main()
{
// declare vars
A a = null;
B b = null;
C c = null;
// a can happily hold references for B.
a = b;
// To call B's methods you need to cast it to B.
((B)a).b();
// a can happily hold references for C.
a = c;
// To call C's methods you need to cast it to C.
a = c;
((C)a).c();
}
}
From your comments
class Program
{
private interface A { }
private interface B : A { string b();}
private interface C : A { string c();}
class BClass : B { public string b() { return "B"; } }
class CClass : C { public string c() { return "C"; } }
private static void Main()
{
A a = null;
B b = new BClass();
C c = new CClass();
a = b;
((B)a).b();
a = c;
((C)a).c();
}
}

Object --> Struct?

How do I take an Object and convert it into a struct and vice visa?
public void myMethod1(object myInputObject, out string myOutputString)
{
myInputObject = null;
myOutputString = "";
//Convert object into a struct, then do something
}
Define a struct and set fields values inside your method.
I suppose you want something like this: (pseudo code)
class myclass
{
public int a;
public float b;
}
struct somestruct
{
somestruct(int a, float b)
{
this.a = a;
this.b = b;
}
int a;
float b;
}
myclass mc = new myclass();
mc.a = 125;
mc.b = 12.5;
somestruct s = new somestruct(mc.a, mc.b); //all fields of mc are now in struct somestruct

Operators overloading in other classes

Can I overload operators for class A in class B in C#? For example:
class A
{
}
class B
{
public static A operator+(A x, A y)
{
...
}
}
No; one of the parameters must be the containing type.
From section §10.10.2 of the language specification (version 4.0):
The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:
• A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
You should think about why. Here's one reason.
class A { }
class B { public static A operator+(A first, A second) { // ... } }
class C { public static A operator+(A first, A second) { // ... } }
A first;
A second;
A result = first + second; // which + ???
Here's another:
class A { public static int operator+(int first, int second) { // ... } }
Assume this allowed for a moment.
int first = 17;
int second = 42;
int result = first + second;
Per the specification for operator overload resolution (§7.3.2), A.+ will have precedence over Int32.+. We've just redefined addition for ints! Nasty.
No, you can't. error CS0563: One of the parameters of a binary operator must be the containing type
"In each case, one parameter must be the same type as the class or struct that declares the operator" quote from
Documentation on overloading operators.
Generally saying NO, but you can do something like following, if it helps :)
class A
{
public static A operator +(A x, A y)
{
A a = new A();
Console.WriteLine("A+"); // say A
return a;
}
}
class B
{
public static A operator +(A x, B y)
{
A a = new A();
Console.WriteLine("return in:A,B in out:A in class B+"); // say B
return a;
}
public static A operator +(B x, B y)
{
A a = new A();
Console.WriteLine("return in:B,B in out:A in class B +");
return a;
}
// and so on....
}
B b = new B();
A a = new A();
A a1 = new A();
B b1 = new B();
a = b + b1; // here you call operator of B, but return A
a = a + a1; // here you call operator of A and return A
To understand your problem, can i ask why you want to do that? :)

Categories