c# class reference as opposed to instance reference - c#

Can I locally reference a class in C#, instead of an instance of a class? The following code won't compile but, as an example, something like:
void someFunc()
{
var a = System.Math;
var b = a.Abs(4);
}
edit: In the real program it's not the System.Math class and I'm wanting to construct the class and return the constructed value. I didn't think originally that the context in which I wanted to use the class would be relevent, and probably it shouldn't be.
Anastasiosyal has an interesting idea with using a local Delegate to do it.

You can reference a class:
Type math = typeof(System.Math);
But you cannot call static methods on it using regular dot syntax:
// Wont compile:
math.Abs(5);
If you just want to shorten (and IMHO obfuscate) your code, you can reference classes with aliases via a using directive:
// Untested, but should work
namespace MyUnreadableCode {
using m = System.Math;
class Foo {
public static Int32 Absolut(Int32 a) {
return m.Abs(a);
}
}
}

You cannot assign a variable a value of a static class. The question is why would you want to do this, there are probably other ways that you could tackle your problem
e.g. you could use delegates to assign the operation you want to perform:
Func<int,int> operation = Math.Abs;
// then you could use it like so:
int processedValue = operation(-1);

In c# they're called Types. And you can assign them like:
Type a = typeof(SomeClass);
However, you would have to instantiate it to use it. What I believe you want is a static import like in java, but unfortunately, they do not exist in c#.
Short answer: Not like what you have above.

In C# 6.0 they introduced a static import feature, which can solve the problem.
using static System.Math;
class MyProgram
{
static void Main(string[] args)
{
var b = Abs(4); // No need to specify the name of Math class
}
}

As I understand you need to refer to the class with short name? try this (on top of the file, inside using statements section):
using m = System.Math;
later in your code:
m.Abs(...)
Makes sense?

No. It's not possible to treat a Type as a value where instance methods bind to static methods on the original type. In order to do this you would need to construct a new type which forwards it's method calls to the original type.
class MyMath {
public int Abs(int i) {
return Math.Abs(i);
}
}
var x = new MyMath();

Related

Assinging a static function from a class to a variable

I want to be able to assign functions from classes to variables
Ex:
namespace test
{
class init
{
static void Main(string[] args)
{
var toSingle = BitConverter.ToSingle;
}
}
}
ERROR The delegate type could not be inferred.
I rather think you might want using static (applied to the top of the file with your other using imports, or just inside your namespace):
using static BitConverter;
This will allow you to simply call ToSingle(...) anywhere in your class.
using static docs
Alternatively, if you really want to assign it to a variable, you could potentially assign it to a delegate (here I'll use Func):
Func<byte[], int, float> toSingle = BitConverter.ToSingle;
Though this won't work if you want to use the overload that takes a ReadOnlySpan<Bye> because it can't be a generic parameter.

How is it possible for me to use "ToArray<T>()" on a variable of type "IEnumerable<out T>"

After saving an anonymous type into a variable of type "IEnumerable" using LINQ, I discovered that it is possible to use several methods that were defined inside of the class "Enumerable" over the aforementioned variable. How is this possible? It should also be noted that "IEnumerable" is an interface.
Here is a small code example:
class MyClass
{
public string Name;
}
class Program
{
static void Main(string[] args)
{
MyClass[] myArray =
{
new MyClass{Name = "Bill"},
new MyClass{Name = "Bill"},
new MyClass{Name = "Steve"}
};
IEnumerable<MyClass> variable = from myInstance in myArray
where myInstance.Name == "Bill"
select myInstance;
MyClass[] newArray = variable.ToArray<MyClass>(); // How is it possible for me to use "ToArray<T>()" on "varialble"?
}
}
This uses a C# feature called extension methods. The method is defined in a separate class (hence the name - it extends the functionality of the original class/interface). The first parameter is prefixed by the this keyword, and the method can be called as if it's a method on that parameter (i.e. on your IEnumerable<MyClass>).
In your example, you are using a library called LINQ, which is composed entirely of extension methods. You can see the source code for ToArray on github. Your code will have using System.Linq; at the top, which is what allows you to call the method in your code.

C# typedef generics

I am using a shorthand version for a class, which looks like this:
using NodeSteps = Tuple<Node, int>;
Node is a class defined by myself. This works fine usually, but the problem here is, is that Node is a generic requiring a struct.
My questions are as follows:
1.
How are these typedefs called in C#. I know they are not exactly typedefs, but it was the most similar thing I could think of.
2.
How can I make a generic version?
using NodeSteps<T> = Tuple<Node<T>, int>;
I noticed this is not the way to do it. I also would like to specify T is a struct.
Use
class NodeSteps<T> : Tuple<Node<T>, int>
{
}
This is the closest equivalent to a typedef I know of. If there are any non-default constructors, you would need to declare them, though.
They are called aliases.
No, this isn't possible. C# Language spec:
Using aliases can name a closed constructed type, but cannot name an unbound generic type declaration without supplying type arguments.
Therefore, using x<T> = List<T> or something similar isn't possible.
You may use a class (see the other answers(s)) instead.
This is covered in section 9.4.1 of the C# Language spec.
Using aliases can name a closed constructed type, but cannot name an
unbound generic type declaration without supplying type arguments.
This is called alias and can not be generic, but right hand of the using can be generic
using ListOfInts = List<int>
is valid
using NodeSteps = Tuple<Node, int>;
is not the equivalent of a typdef but just an alias to that class. It's designed to work around namespace collisions without having to use the whole namespace. What I would do is define a new class:
public class NodeSteps<T> : Tuple<Node<T>, int> where t: struct
{
}
This works:
namespace Test1
{
class Node<T>
{
public T Test()
{
return default(T);
}
}
}
namespace Test1
{
using NodeSteps = System.Tuple<Node<string>, int>;
public class Class1
{
public static void Main()
{
NodeSteps t1 = new NodeSteps(new Node<string>(), 10);
t1.Item1.Test();
}
}
}

C# simpler run time generics

Is there a way to invoke a generic function with a type known only at run time?
I'm trying to do something like:
static void bar()
{
object b = 6;
string c = foo<typeof(b)>();
}
static string foo<T>()
{
return typeof (T).Name;
}
Basically I want to decide on the type parameter only at run time, but the function I'm calling depends on the type parameter.
Also I know this can be done with reflections... but it's not the nicest solution to the problem...
I'm sort of looking for dynamic features in C#...
I'm writhing a bridge between two classes the first one is basically a big tree with different types of of objects (composite by interface) the other is a sort of a "super visitor".
the supper visitor accepts key-value dictioneries that map types to object it looks like:
dic.Add(object value)
and T is not necessarily the type of the value... a lot of times it isn't...
I know it's written poorly, but i can't fix it...
I can work around it, but only at runtime...
I already did it with reflections, but if there's a better way to do it without them i would be happy to learn...
Thank you
This is a bit of a hack but you can get dynamic to do the reflection work for you by something like,
class Program
{
static void Main(string[] args)
{
var b = 6;
var t = (dynamic)new T();
var n = t.Foo(b);
}
class T
{
public string Foo<T>(T a)
{
return typeof(T).Name;
}
}
}
Here the dynamic call will extract the type of b and use it as a type parameter for Foo().
You can use dynamic keyword if you're using .NET 4. In a word, the type of the variable will be resolved at run time so it is a super generic type ;) You can read a article here or read the MSDN documentation
Saly refelction is THE solution to the problem, whether it is nice or not is irrelevant here. It is the runtime designed mechanism to achieve exactly this. As there is no parameter or generics to use as input, this is the only way to do it - it is also senseless. As in: your example is bad. Because in the example the type is hardcoded.
If the method where b exists has b as generic parameter, the type is available for passing to foo. If not - reflection is THE way to go, albeit the syntax looks clumsy. Only one time, though.
This I believe is the only way:
var foo = typeof(Foo<>).MakeGenericType(typeof (bar));
You can set up a class which takes a type parameter at run time which can be used in the methods in that class.
public class GenericClass<T>()
{
ICommonInterface TheObject;
public GenericClass(T theObject)
{
TheObject = theObject;
}
public string GetName()
{
return TheObject.Name;
}
}
But this is only really useful if the Types being passed in share interfaces so have common properties between them. In your example it seems that relection is the answer as depending on the type you want to access specific properties.

Dynamically create an object of <Type>

I have a table in my database that I use to manage relationships across my application. it's pretty basic in it's nature - parentType,parentId, childType, childId... all as ints. I've done this setup before, but I did it with a switch/case setup when I had 6 different tables I was trying to link. Now I have 30 tables that I'm trying to do this with and I would like to be able to do this without having to write 30 case entries in my switch command.
Is there a way that I can make reference to a .Net class using a string? I know this isn't valid (because I've tried several variations of this):
Type t = Type.GetType("WebCore.Models.Page");
object page = new t();
I know how to get the Type of an object, but how do I use that on the fly to create a new object?
This link should help:
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance
Activator.CreateInstance will create an instance of the specified type.
You could wrap that in a generic method like this:
public T GetInstance<T>(string type)
{
return (T)Activator.CreateInstance(Type.GetType(type));
}
If the type is known by the caller, there's a better, faster way than using Activator.CreateInstance: you can instead use a generic constraint on the method that specifies it has a default parameterless constructor.
Doing it this way is type-safe and doesn't require reflection.
T CreateType<T>() where T : new()
{
return new T();
}
public static T GetInstance<T>(params object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
I would use Activator.CreateInstance() instead of casting, as the Activator has a constructor for generics.
You want to use Activator.CreateInstance.
Here is an example of how it works:
using System;
using System.Runtime.Remoting;
class Program
{
static void Main()
{
ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32");
Int32 i = (Int32)o.Unwrap();
}
}
Assuming you have the following type:
public class Counter<T>
{
public T Value { get; set; }
}
and have the assembly qualified name of the type, you can construct it in the following manner:
string typeName = typeof(Counter<>).AssemblyQualifiedName;
Type t = Type.GetType(typeName);
Counter<int> counter =
(Counter<int>)Activator.CreateInstance(
t.MakeGenericType(typeof(int)));
counter.Value++;
Console.WriteLine(counter.Value);
Here is a function I wrote that clones a record of type T, using reflection.
This is a very simple implementation, I did not handle complex types etc.
public static T Clone<T>(T original)
{
T newObject = (T)Activator.CreateInstance(original.GetType());
foreach (var prop in original.GetType().GetProperties())
{
prop.SetValue(newObject, prop.GetValue(original));
}
return newObject;
}
I hope this can help someone.
Assaf

Categories