C# type of enclosing class - c#

Is there some way to specify the type of the enclosing class declaration statically? If i had an instance, I could clearly use typeof(this), but statically I don't see a way.
Something like (where this_type is a placeholder):
public class Message
{
public static readonly int SizeInBytes = Marshal.SizeOf(typeof(this_type));
}
Clearly, I could just use the actual type name, but I've got several classes that follow this pattern and would like something less copy/paste error prone.

You can use MethodBase.GetCurrentMethod().DeclaringType but typeof(Message) is probably the cleaner way
public class Message
{
public static readonly int SizeInBytes = Marshal.SizeOf(MethodBase.GetCurrentMethod().DeclaringType);
}
Btw, you'll get a runtime exception when you execute this code as it is trying to get the size of a managed object.

typeof(Message) would be the closest you'd get here, but I think you'd need to use a struct rather than a class to do this from what I recall.

Perhaps:
public class Message
{
public static readonly int SizeInBytes = Marshal.SizeOf(typeof(Message));
}
This way, 'Message' can also be static.

What about an extension method on the type and get it dynamically instead of pushing it to a readonly static variable?
public static class Extensions
{
public static int SizeOfType(this System.Type tp) {
return Marshal.SizeOf(tp);
}
public static int SizeOfObjectType(this object obj) {
return obj.GetType().SizeOfType();
}
}
// calling it from a method, 2 ways
var size1 = this.GetType().SizeOfType();
var size2 = this.SizeOfObjectType();
var size3 = typeof(string).SizeOfType();
var size4 = "what is my type size".SizeOfObjectType();

After a short google search, I've seen other people using reflection to accomplish what you are talking about, but that comes with the caveat that it is probably a lot more expensive than just typing out typeof(this_type). I'd sooner recommend just typing it out.
Type t = MethodBase.GetCurrentMethod().DeclaringType
.NET: Determine the type of “this” class in its static method

Related

C# Get property value without creating instance?

Is it possible to get value without creating an instance ?
I have this class:
public class MyClass
{
public string Name{ get{ return "David"; } }
public MyClass()
{
}
}
Now I need get the value "David", without creating instance of MyClass.
Real answer: no. It's an instance property, so you can only call it on an instance. You should either create an instance, or make the property static as shown in other answers.
See MSDN for more information about the difference between static and instance members.
Tongue-in-cheek but still correct answer:
Is it possible to get value without creating an instance ?
Yes, but only via some really horrible code which creates some IL passing in null as this (which you don't use in your property), using a DynamicMethod. Sample code:
// Jon Skeet explicitly disclaims any association with this horrible code.
// THIS CODE IS FOR FUN ONLY. USING IT WILL INCUR WAILING AND GNASHING OF TEETH.
using System;
using System.Reflection.Emit;
public class MyClass
{
public string Name { get{ return "David"; } }
}
class Test
{
static void Main()
{
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var dynamicMethod = new DynamicMethod("Ugly", typeof(string),
Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Ldnull);
generator.Emit(OpCodes.Call, method);
generator.Emit(OpCodes.Ret);
var ugly = (Func<string>) dynamicMethod.CreateDelegate(
typeof(Func<string>));
Console.WriteLine(ugly());
}
}
Please don't do this. Ever. It's ghastly. It should be trampled on, cut up into little bits, set on fire, then cut up again. Fun though, isn't it? ;)
This works because it's using call instead of callvirt. Normally the C# compiler would use a callvirt call even if it's not calling a virtual member because that gets null reference checking "for free" (as far as the IL stream is concerned). A non-virtual call like this doesn't check for nullity first, it just invokes the member. If you checked this within the property call, you'd find it's null.
EDIT: As noted by Chris Sinclair, you can do it more simply using an open delegate instance:
var method = typeof(MyClass).GetProperty("Name").GetGetMethod();
var openDelegate = (Func<MyClass, string>) Delegate.CreateDelegate
(typeof(Func<MyClass, string>), method);
Console.WriteLine(openDelegate(null));
(But again, please don't!)
You can make that property static
public static string Name{ get{ return "David"; } }
Usage:
MyClass.Name;
You requirements do seem strange, but I think you're looking for some kind of metadata. You can use an attribute to achieve this:
public class NameAttribute : Attribute {
public string Name { get; private set; }
public NameAttribute(string name) {
Name = name;
}
}
[Name("George")]
public class Dad {
public string Name {
get {
return NameGetter.For(this.GetType());
}
}
}
[Name("Frank")]
public class Son : Dad {
}
public static class NameGetter {
public static string For<T>() {
return For(typeof(T));
}
public static string For(Type type) {
// add error checking ...
return ((NameAttribute)type.GetCustomAttributes(typeof(NameAttribute), false)[0]).Name;
}
}
Now this code can get names with and without instances:
Console.WriteLine(new Dad().Name);
Console.WriteLine(new Son().Name);
Console.WriteLine(NameGetter.For<Dad>());
Console.WriteLine(NameGetter.For<Son>());
You can make your property static, as pointed out by many others.
public static string Name{ get{ return "David"; } }
Be aware that this means your instances of MyClass will no longer have their own Name property, since static members belong to the class, not the individual object instances of it.
Edit:
In a note, you mentioned that you want to override the Name property in subclasses. At the same time, you want to be able to access it at the class level (access it without creating an instance of your class).
For the static properties, you would simply create a new Name property in each class. Since they are static, you're always (almost always, yay reflection) going to access them using a specific class, so you'd be specifying which version of Name you want to get. If you want to try and hack polymorphism in there and get the name from any given subclass of MyClass, you could do so using reflection, but I wouldn't recommend doing so.
Using the example from your comment:
public class Dad
{
public static string Name { get { return "George"; }
}
public class Son : Dad
{
public static string Name { get{ return "Frank"; }
}
public static void Test()
{
Console.WriteLine(Dad.Name); // prints "George"
Console.WriteLine(Son.Name); // prints "Frank"
Dad actuallyASon = new Son();
PropertyInfo nameProp = actuallyASon.GetType().GetProperty("Name");
Console.WriteLine(nameProp.GetValue(actuallyASon, null)); // prints "Frank"
}
As a side note, since you are declaring a property that has only a getter and it is returning a constant value, I recommend possibly using a const or static readonly variable instead.
public const string Name = "David";
public static readonly string Name = "David";
Usage for both would be the same:
string name = MyClass.Name;
The main benefit (and drawback) of const is that all references to it are actually replaced by its value when the code is compiled. That means it will be a little faster, but if you ever change its value, you will need to recompile ALL code that references it.
Whenever you write C# code, always check if your method and property getter/setter code does anything at all with other instance members of the class. If they don't, be sure to apply the static keyword. Certainly the case here, it trivially solves your problem.
The reason I really post to this question is that there's a bit of language bias at work in some of the answers. The C# rule that you can't call an instance method on a null object is a specific C# language rule. It is without a doubt a very wise one, it really helps to troubleshoot NullReferenceExceptions, they are raised at the call site instead of somewhere inside of a method where it gets very hard to diagnose that the this reference is null.
But this is certainly not a requirement to the CLR, nor of every language that run on the CLR. In fact, even C# doesn't enforce it consistently, you can readily bypass it in an extension method:
public static class Extensions {
public static bool IsNullOrEmpty(this string obj) {
return obj != null && obj.Length > 0;
}
}
...
string s = null;
bool empty = s.IsNullOrEmpty(); // Fine
And using your property from a language that doesn't have the same rule works fine as well. Like C++/CLI:
#include "stdafx.h"
using namespace System;
using namespace ClassLibrary1; // Add reference
int main(array<System::String ^> ^args)
{
MyClass^ obj = nullptr;
String^ name = obj->Name; // Fine
Console::WriteLine(name);
return 0;
}
Create a static property:
public class MyClass
{
public static string Name { get { return "David"; } }
public MyClass()
{
}
}
Get it like so:
string name1 = MyClass.Name;
That is not possible. As Name is an instance property, you can only get its value if you have an instance.
Also, note that you are not talking about a parameter, but about a property.
Create a static class or a static property, and you don't have to explicitly instantiate it.

Function Declarations with Generics in C#

I have a function that is declared like so:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
I am trying to pass it a variable called whereAnd which is delcared like so:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
WhereAndCondition is a sub class of WhereCondition. It is declared like so:
public class WhereAndCondition<T> : WhereCondition<T>, IConditional where T : DatabaseObject
My issue is, if I try to execute the following code:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
I get the following error:
Error 3 Argument 1: cannot convert from 'System.Collections.Generic.List<BrainStorm.WhereAndCondition<T>>' to 'System.Collections.Generic.List<BrainStorm.WhereCondition<T>>'
Any ideas on why? I think it has to do with the generics of the WhereCondition classes.
I would suggest using interfaces:
public static string MultiWhereToString(IEnumerable<ICondition<T>> whereConditions)
This would allow you a lot more freedom when calling this method.
Given:
class A {}
class A : B {}
An object of List<B> is not an instance of List<A>. So you can't cast a List<WhereAndCondition> to a List<WhereCondition>. You could use:
MultiWhereToString(whereAnd.OfType<WhereCondition>().ToList());
(There might also be a solution involving the in and out variance annotations, but I'm not terribly familiar with them.)
Your function is defined as taking a WhereCondition List, but you're passing it a WhereAndCondition List:
MultiWhereToString(List<WhereCondition<T>> whereConditions)
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
MultiWhereToString(whereAnd);
List variance has limited supported in .NET 4. See this question.
You can replace the entire WhereCondition<T> in your MultiWhereToString method with another generic type which is restricted to WhereCondition<T>.
Replace:
public static string MultiWhereToString(List<WhereCondition<T>> whereConditions)
With:
public static string MultiWhereToString<TType>(List<TType> whereConditions) where TType: WhereCondition<T>
Or alternatively change:
private List<WhereAndCondition<T>> whereAnd = new List<WhereAndCondition<T>>();
to:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
And let inheritance take care of the rest for you.
This appears to be a covariance / contravariance issue.
Simplified to this:
public class WhereCondition
{
}
public class WhereAndCondition : WhereCondition
{
}
public class blah
{
public static void Blah()
{
List<WhereAndCondition> whereAnd = new List<WhereAndCondition>();
MultiWhereToString(whereAnd);
}
public static string MultiWhereToString(List<WhereCondition> whereConditions)
{
return null;
}
}
It's not going to work, because the list of WhereAndConditions can't be cast to List of WhereConditions:
Imagine it this way. You've got a list of giraffes, and the method is asking for a list of animals.
Without knowing what they are going to do with the list animals (like try adding a horse) the types are incompatible, but if you change it to something like this:
public static string MultiWhereToString(IEnumerable<WhereCondition> whereConditions)
{
return null;
}
Then the variance can kick in, and give you what you're looking for.
Generics have to be known explicitly at compile time because they are generated.
Why not use:
private List<WhereCondition<T>> whereAnd = new List<WhereCondition<T>>();
So you can still add WhereAndCondition objects to whereAnd.

Creating a Generic Class Member for Extra Info

I'm very new to C# (this is my first C# project). I'm fairly confident with the basics, but I'm starting to run into things that are raising issues that I can't quite solve, no matter how many different ways I Google it. A LOT of my questions have been answered by this site. :]
So, since I can't find the answer to this question, I decided to post it myself.
Maybe it's too basic of a question that everyone pretty much knows it, but I couldn't figure this out from the MSDN reading.
It has to do with C# Generics. I'm programming for a video game engine, and I've created a simple messaging system between AI units. The Message class contains members like sender, receiver, dispatchTime, and extraInfo. I want to use the extraInfo member to be a useful, flexible addition to the Message class, so I would like for it to be able to contain any type (an int node index, a double path cost, a relevant Vector3 position from XNA, etc, etc...). My research for this pointed me in the direction of Generics.
I figured out how to use Generics in something like a List, but I haven't read anything about how to just declare and implement a generic -member-. Just a single member, not a collection.
How would I declare this member, extraInfo? Additionally, when accessing it from another class, I would like to be able to type:
info = message.extraInfo;
..to retrieve the extra information via the get property.
How would this be done in C#?
Your message class would look something like this
public class Message<T>
{
public object Sender { get; set; }
public object Receiver { get; set; }
public T ExtraInfo { get; set; }
}
public static void Main()
{
Message<double> doubleMessage = new Message<double>() { ExtraInfo = 4.0d };
Message<string> stringMessage = new Message<string>() { ExtraInfo = "Hello World" };
}
Using .NET 4.0, you can make your ExtraInfo property of type dynamic. You could then store anything at all in it, and as long as you access it properly at runtime, you'll be ok.
You could declare the extraInfo member of your class as an object. You could then put anything you want in there.
You can solve your problem by creating an ExtraInfoType object that contains an
object as well as implicit operators to convert to and from the various object types transparently.
The ExtraInfoType object can also indicate what kind of object is stored in the ExtraInfoType.
An example of this implementation is below.
enum ExtraInfoKind
{
Integer,
Double
}
class ExtraInfoType
{
object value;
public object Value {
get { return value; }
}
ExtraInfoKind kind;
public ExtraInfoKind Kind {
get { return kind; }
}
private ExtraInfoType(object o, ExtraInfoKind kind){
this.value=o;
this.kind=kind;
}
public static implicit operator int(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Integer)
throw new InvalidCastException();
return (int)o.value;
}
public static implicit operator double(ExtraInfoType o){
if(o.kind!= ExtraInfoKind.Double)
throw new InvalidCastException();
return (double)o.value;
}
public static implicit operator ExtraInfoType(int o){
return new ExtraInfoType(o, ExtraInfoKind.Integer);
}
public static implicit operator ExtraInfoType(double o){
return new ExtraInfoType(o, ExtraInfoKind.Double);
}
}
/* Example
class Program
{
public static void Main(string[] args)
{
ExtraInfoType t=1;
Console.WriteLine(t.Kind);
int valueT=t;
Console.WriteLine(t);
Console.ReadLine();
}
}
*/
Here you would declare extraInfo under the type ExtraInfoType.
Note that no generics are necessary here. Note also that ExtraInfoType
can store only one kind of object, which can be determined by the Kind property.
If the object is cast to the wrong type, an InvalidCastException is thrown, as
can be seen in the implicit operators above.

Define "dynamic" enum

I'm working on this project and I have a large number of "services" to execute. I need to have this service codes so I can verifiy and make decisions according to selected services by it's code.
I'm tring to define this enum and get its values from the web.config so I can change them easily.
public enum ServiceCodes
{
Transfer= Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"]),
ChangePlate= Convert.ToInt32(ConfigurationManager.AppSettings["servChangePlate"])
}
But I get this error: The expression must be constant. (because of the Conversion)
What can I do? (Or you can suggest me totally different approaches.)
Just go ahead and define a static class like this:
public static class ServiceCodes
{
readonly static int Transfer = Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"])
//...
}
The documentation states that enum values are constant. An alternative approach is to declare a class with static readonly members.
If you still need the type safety provided by an enum, you could use a slightly complex approach:
public class ServiceCodes {
public static readonly ServiceCodes Transfer = new ServiceCodes(Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"]));
public static readonly ServiceCodes ChangePlate = new ServiceCodes(Convert.ToInt32(ConfigurationManager.AppSettings["servChangePlate"]));
internal int Code {get; private set;}
private ServiceCodes(int code) {
Code = code;
}
}
Then, a method like:
public void SomeAction(ServiceCodes serviceCode) {
//....
}
could be called like this:
SomeAction(ServiceCodes.Transfer);
But, given the complexity (compared with the gain), I would go with the first approach.

What is a good way to handle enums that need to be strings

I'm pretty sure an enum isn't what I want. What I want is a list of named items
CustomerLookup = "005",
CustomerUpdate = "1010"
The "005" and "1010" aren't my values, they are the values I need to send to a 3rd party that I have no control over. There are close to 500 of them. I just want my code to look nice.
Instead of
SendRequest("005");
I'd rather see
SendRequest(RequestType.CustomerLookup);
Anyone have any self-documenting ideas without getting all crazy in the code?
Anything wrong with:
public static class RequestType
{
public static readonly string CustomerLookup = "005";
// etc
}
or
public static class RequestType
{
public const string CustomerLookup = "005";
// etc
}
? Or if you want more type safety:
public sealed class RequestType
{
public static readonly RequestType CustomerLookup = new RequestType("005");
// etc
public string Code { get; private set; }
private RequestType(string code)
{
this.Code = code;
}
}
That will basically give you a fixed set of values (the constructor is private, so outside code can't create different instances) and you can use the Code property to get at the related string value.
How about using some kind of associative array?
The way you are already doing it seems right to me.
You are clearly defining the requesttype values in your code without ambiguity and when you come to use them you have intellisense on your side.
I think the real issue is how to get the 500 values into your code without any tyypos!

Categories

Resources