C#: How to set default value if input is empty - c#

If I have a method like this:
public void AddSomething(string ice = "10", string sweet = "20")
{
Console.Write(ice);
Console.Write(sweet);
}
so if I input a string, it will write the string. If not, it will write the default string(10,20).
But I want something like this:
public void AddSomething(string ice = "10", string sweet = "20")
{
if(ice = "")
ice = default_vaule; //which is 10
if(sweet = "")
sweet = default_vaule; //which is 20
Console.Write(ice);
Console.Write(sweet);
}
so if user input a empty string "", I can write the default value to user, so I can do not only this:
AddSomething("5");
Also both of these:
AddSomething("5","");
AddSomething("","5");
Anyone knows how to do that? THX!

you already answered your question. you can cover null cases also.
public void AddSomething(string ice = "10", string sweet = "20")
{
if(string.IsNullOrEmpty(ice)) ice = "10";
if(string.IsNullOrEmpty(sweet)) sweet = "20";
Console.Write(ice);
Console.Write(sweet);
}
you can use constants if you don't want to write duplicate literals.
// these are constant and can be used as default value for parameters.
const string DefaultSweet = "20";
const string DefaultIce = "10";
public void AddSomething(string ice = DefaultSweet, string sweet = DefaultIce)
{
if(string.IsNullOrEmpty(ice)) ice = DefaultIce;
if(string.IsNullOrEmpty(sweet)) sweet = DefaultSweet;
Console.Write(ice);
Console.Write(sweet);
}
side note: string.IsNullOrEmpty(ice) is equivalent to ice == "" || ice == null

So you want to get the default value of a method-parameter at runtime without repeating yourself, so without typing that value again(f.e. to prevent that have you change it there too if you change the default value of the parameter)?
That's not easy because there is no defaultof(parameter)-operator (similar to the nameof-operator). You had to use reflection.
You could use this extension:
public static class MethodExtensions
{
public static Result<T> ParameterDefault<T>(this MethodBase m, string paramName)
{
ParameterInfo parameter = m.GetParameters()
.FirstOrDefault(p => p.Name == paramName);
if (parameter == null)
throw new ArgumentException($"No parameter with given name '{paramName}' found", nameof(paramName));
if (parameter.ParameterType != typeof(T))
throw new ArgumentException($"Parametertype is not '{typeof(T)}' but '{parameter.ParameterType}'");
if(parameter.HasDefaultValue)
return new Result<T>((T)parameter.DefaultValue, true);
else
return new Result<T>(default(T), false);
}
}
which returns an instance of following class, which is just a wrapper to enable to also return the information if the default value could be determined:
public class Result<T>
{
public Result(T value, bool success)
{
Value = value;
Success = success;
}
public T Value { get; private set; }
public bool Success { get; private set; }
}
Now your method looks like:
public void AddSomething(string ice = "10", string sweet = "20")
{
MethodBase m = MethodBase.GetCurrentMethod();
if (ice == "")
ice = m.ParameterDefault<string>(nameof(ice)).Value;
if (sweet == "")
sweet = m.ParameterDefault<string>(nameof(sweet)).Value;
Console.Write(ice);
Console.Write(sweet);
}
and you don't need to repeat the parameter value.

This question ( at least for me ) is unclear but from what you've posted I can suggest solution like this :
// default value for "ice"
const string default_ice = "10";
// default value for "sweet"
const string default_sweet = "20";
public void AddSomething(string ice = default_ice, string sweet = default_sweet)
{
// check if "ice" value is set
if(string.IsNullOrEmpty(ice))
ice = default_ice; // set "ice" value to the default one
// check if "sweet" value is set
if(string.IsNullOrEmpty(sweet))
sweet = default_sweet; // set "sweet" value to the default one
Console.Write(ice);
Console.Write(sweet);
}
You can then also call it like such:
AddSomething(sweet: "1337");
// or
AddSomething("13", "37");
or however you like.
Try this online

Related

C# manipulating data parsed from CSV

I'm creating a program to generate schematics based off of user input. This has to be done dynamically/by hand due to the sheer volume of different possibilities (6.8M, growing exponentially). Right now I'm working on importing some data via CSV.
Example data:
Type,TIN_pos,TIN_ID,Desc
Elect, 0, X, Manual Regulator
Elect, 0, A, Electronic Regulator
Import code:
List<TIN_Fields> values = File.ReadAllLines("C:\\Users\\User\\Desktop\\Visual Basic\\CSV_Test_1.csv")
.Skip(1)
.Select(v => TIN_Fields.FromCsv(v))
.ToList();
public class TIN_Fields
{
public string Type;
public int TIN_pos;
public string TIN_ID;
public string Desc;
public static TIN_Fields FromCsv(string csvLine)
{
string[] values = csvLine.Split(',');
TIN_Fields _Fields = new TIN_Fields();
_Fields.Type = Convert.ToString(values[0]);
_Fields.TIN_pos = Convert.ToInt16(values[1]);
_Fields.TIN_ID = Convert.ToString(values[2]);
_Fields.Desc = Convert.ToString(values[3]);
return _Fields;
}
}
Once that data is Imported, I need to do two things with it,
display the raw csv data in a ListView table, just so users can see if anything in the list needs updating.
be able to compare the items in the list to various characters in a 10-digit hexadecimal code, and spit out some results.
First and foremost, i need to run through the list that was created with the above code, make sure that:
TIN_pos value = 0
because that is the character position of the input box.
Then, with the remaining options, look for the character represented in the input in the TIN_ID field.
Once found, it should then output the Desc field.
Everywhere I have looked says to use foreach, but that requires the array name, which is the part that is confusing me. I've tried filling in basically all of the variables in the FromCSV Method and usually get an error that the class doesn't have a definition.
to hopefully clear up confusion with my explanation, here is the code I created that does the same thing, but with the CSV data hard coded into it, using switch cases and if statements.
public partial class Form1 : Form
{
public string Model_Chassis;
public string Model_Test_Type;
public int ChannelNumberVar => Convert.ToInt32(TextBox_TIN[2]);
public string Tester_Type_Selector;
public string TextBox_TIN
{
get { return TIN_Entry_TextBox.Text; }
set { TIN_Entry_TextBox.Text = value; }
}
public string Model_Data_D
{
get { return Model_Data.Text; }
set { Model_Data.Text = value; }
}
public Form1()
{
InitializeComponent();
}
//Method grabs TIN Box data and decodes it to model information.
public void Model_Select()
{
//Picks Model Chassis
switch (char.ToUpper(TextBox_TIN[0]))
{
case 'H':
{
Model_Chassis = Coding.Model1.description;
}
break;
default:
{
Model_Data_D = "INVALID TIN";
}
break;
}
//Picks Test Type
switch (char.ToUpper(TextBox_TIN[3]))
{
case '0':
{
Model_Test_Type = Test_Types.TT_PD.TT_tt;
}
break;
case '1':
{
Model_Test_Type = Test_Types.TT_PV.TT_tt;
}
break;
default:
{
Model_Test_Type = "";
}
break;
}
//Puts chassis and Test Type together
if (Model_Data_D.Equals("INVALID TIN"))
{
;
}
else if (char.ToUpper(TextBox_TIN[2]).Equals(Coding.Num_Chan_1_2.tin_id))
{
Model_Data_D = $"{Model_Chassis}-{Model_Test_Type}";
}
else
{
Model_Data_D = $"{Model_Chassis}-{TextBox_TIN[2]}{Model_Test_Type}";
}
}
public class Coding
{
public char tin_id;
public string description;
public Coding(char TIN_ID, string Desc)
{
tin_id = TIN_ID;
description = Desc;
}
public static Coding Model1 = new Coding('H', "Model1");
public static Coding Num_Chan_1_2 = new Coding('X', "Single Channel");
public static Coding Elect_Reg_F_1 = new Coding('X', "Manual Regulator");
}
}
INPUT:
HXX0X
OUTPUT
Model1-PD
Thanks in advance for the help!
You're asking quite a few questions, and providing a lot of extra details in here, but for this:
"First and foremost, i need to run through the list that was created with the above code, make sure that:
TIN_pos value = 0
because that is the character position of the input box."
(seeing as you say you need to do this 'first and foremost').
In your FromCsv method, check the value as you create the record, and throw an error if it is invalid. Like this:
public static TIN_Fields FromCsv(string csvLine)
{
string[] values = csvLine.Split(',');
TIN_Fields _Fields = new TIN_Fields();
_Fields.Type = Convert.ToString(values[0]);
_Fields.TIN_pos = Convert.ToInt16(values[1]);
if(_Fields.TIN_pos != 0){
throw new Exception("TIN_pos must be 0");
}
_Fields.TIN_ID = Convert.ToString(values[2]);
_Fields.Desc = Convert.ToString(values[3]);
return _Fields;
}
Assuming you've read in your CSV correctly, which it seems you have, then selecting the appropriate TIN from the list is a simple LINQ statement. The following code assumes that TIN IDs are unique and only a single character in length.
static void Main(string[] args)
{
string testCsv = #"C:\Users\User\Desktop\Visual Basic\CSV_Test_1.csv";
List<TIN_Fields> values = File.ReadAllLines(testCsv)
.Skip(1)
.Select(v => TIN_Fields.FromCsv(v))
.ToList();
// Simulates input received from form
string input = "HXX0X";
TIN_Fields selectedTIN = values.First(x => x.TIN_ID == Convert.ToString(input[0]));
// Insert the description as needed in your ouput.
string output = $"{ selectedTIN.Desc }-";
}
Hopefully that answers another part of the problem. The Convert.ToString() is required because the output of input[0] is a char.

Comparison between three members of an object

Consider objects of the following type:
public class MyObject
{
// "defining" attributes
private string member1;
private string member2;
private string member3;
// other attributes
private string member4;
private string member5;
// ctor
public MyObject(){}
public bool compare(MyObject that)
{
// compare this object with another (that)
}
The compare() method should behave as follows. It only considers "defining" attributes. If they are all different between two objects, it should return false. If they are all the same, return false. In other cases, return true (if only one or two of them differ between the two objects).
The question is, do I have to resort to a huge if statement for this? Is there a "better" solution?
Instead of creating n number of strings, you can create property called List<string> DefiningAttributes and List<string> OtherAttributes.
Now add values to this lists where you want, for now I am doing it in constructor. Use Except() method to get difference from DefiningAttributes and OtherAttributes
Check below implementation
public class MyObject
{
// "defining" attributes
public List<string> DefiningAttributes { get; set; }
// other attributes
public List<string> OtherAttributes { get; set; }
public MyObject()
{
//I used constructor to assign values
DefiningAttributes = new List<string>() { "ABC", "PQR", "XYZ" };
OtherAttributes = new List<string>() { "ABC", "PQR", "Stackoverflow" };
}
public bool compare(MyObject that)
{
var difference = this.DefiningAttributes.Except(that.DefiningAttributes);
//Return false If they are all different between two objects OR if they are all same
if(difference.Count() == this.DefiningAttributes.Count() || !difference.Any())
return false;
//Otherwise return true
return true;
}
}
For more details, read Enumerable.Except method
I think this should do it
var comp1 = this.member1 == that.member1;
var comp2 = this.member2 == that.member2;
var comp3 = this.member3 == that.member3;
var comparisons = new List<string>() { comp2, comp3 };
return comparisons.Any(val => val != comp1 );
comp1, comp2 and comp3 will be bools. If any of those comparisons are not the same as the first comparison*, we know we have different results.
[*] You could use any reference point instead of the first comparison
Edit: Whoops, I thought this was a javascript question, but I then realized it was C#. I just changed my answer to use C# syntax, but the idea is the same. This requires the Linq extension method Any.
The following code should do the trick.
If you want to increase the number of defining properties you just edit the size of the array or swap it to a list.
It should iterate over them and when one does not mach return true.
If at the end none matches returns false.
public class MyObject
{
// "defining" attributes
public string[] definingAttributes = new string[3];
// other attributes
private string member4;
private string member5;
// ctor
public MyObject() { }
public bool compare(MyObject that)
{
bool? previousResult = null;
// compare this object with another (that)
for (int i = 0; i < definingAttributes.Length; i++)
{
if (previousResult == null)
{
previousResult = definingAttributes[i] == that.definingAttributes[i];
}
if (definingAttributes[i] != that.definingAttributes[i])
{
if (previousResult != (definingAttributes[i] == that.definingAttributes[i]))
{
return true;
}
}
}
return false;
}
}

In C#, is it possible to call a method (which has default parameters) with "as many parameters as I have"?

That is, I have a method such as the following:
public static int CreateTaskGroup(string TaskGroupName,
string Market = "en-us", string Project = "MyProject",
string Team = "DefaultTeam", string SatelliteID="abc");
I would like to call this method from the command line, by reading the standard array of command line arguments. The obvious way to do it would be as follows:
if (args.Length == 1) CreateTaskGroup(args[0]);
if (args.Length == 2) CreateTaskGroup(args[0], args[1]);
if (args.Length == 3) CreateTaskGroup(args[0], args[1], args[2]);
Is it possible to do this in a more concise way?
Here's one alternative, with the downside that you have to redeclare the default value constants:
CreateTaskGroup(
args[0],
args.ElementAtOrDefault(1) ?? "en-us",
args.ElementAtOrDefault(2) ?? "MyProject",
args.ElementAtOrDefault(3) ?? "DefaultTeam",
args.ElementAtOrDefault(4) ?? "abc");
You can reduce this issue by declaring the strings as consts, e.g.:
public const string MarketDefault = "en-us";
public static int CreateTaskGroup(string TaskGroupName,
string Market = MarketDefault, ...)
static void Main(string[] args)
{
CreateTaskGroup(
args[0],
args.ElementAtOrDefault(1) ?? MarketDefault,
...);
}
But then it's not guaranteed by the compiler, nor overtly obvious, that MarketDefault is, in fact, still (code can be refactored in the future) the default for Market.
Edit: Here's an alternate solution, using reflection:
var argsForMethod = new List<string>(args);
var m = typeof(Program).GetMethod("CreateTaskGroup");
foreach (var p in m.GetParameters().Skip(args.Length))
if (p.Attributes.HasFlag(ParameterAttributes.HasDefault))
argsForMethod.Add((string)p.DefaultValue);
else
throw new NotImplementedException();
var result = (int)m.Invoke(null, argsForMethod.ToArray());
This can be a bit hard to read, and won't be too fast, but it does what you asked, without resorting to repetitive code, or having any uncertainty as to the default value of the parameters. You'll probably want to add some error handling for too few or too many parameters. I prefer this solution.
How about using params in CreateTaskGroup something like this
public static int CreateTaskGroup(params string[] args)
{
for ( int i = 0 ; i < args.Length ; i++ )
{
............
This is how I would implement the class to keep things clean and to assign the responsibility of knowing the default values to the TaskGroupCreator.
public class TaskGroupCreator
{
private string[] values;
public TaskGroupCreator(string[] values)
{
this.values = values;
}
public string TaskGroupName
{
get { return values[0]; }
}
public string Market
{
get { return this.GetElement(1, "en-us"); }
}
public string Project
{
get { return this.GetElement(2, "MyProject"); }
}
public string Team
{
get { return this.GetElement(3, "DefaultTeam"); }
}
public string SatelliteID
{
get { return this.GetElement(4, "abc"); }
}
public int CreateTaskGroup()
{
// Do stuff with your properties...
}
private string GetElement(int index, string defaultValue)
{
return this.values.ElementAtOrDefault(index) ?? defaultValue;
}
}
Usage:
var taskGroup = new TaskGroupCreator(args).CreateTaskGroup();
I'd do it this way..
CreateTaskGroup(args);
//.....
public static int CreateTaskGroup(params string[] args) {
if (args.Length == 0) throw new Exception("nope!");
args = args.Concat(Enumerable.Range(0, 5 - args.Length)
.Select<int, string>(_ => null)).ToArray();
string TaskGroupName = args[0];
string Market = args[1] ?? "en-us";
string Project = args[2] ?? "MyProject";
string Team = args[3] ?? "DefaultTeam";
string SatelliteID = args[4] ?? "abc";
//......
}
params keyword isn't mandatory, but could be convenient...
This is probably best out of what I've come up with:
public static int CreateTaskGroup(string[] arguments)
{
// optional error handling here
string TaskGroupName = arguments[0];
string Market = arguments.ElementAtOrDefault(1) ?? "en-us";
string Project = arguments.ElementAtOrDefault(2) ?? "MyProject";
string Team = arguments.ElementAtOrDefault(3) ?? "DefaultTeam";
string SatelliteID = arguments.ElementAtOrDefault(4) ?? "abc";
// function body as it was
This does the same thing but is less concise:
public static int CreateTaskGroup(string[] arguments)
{
string TaskGroupName, Market, Project, Team, SatelliteID;
switch (arguments.Length)
{
case 5:
string SatelliteID = arguments[4] ?? "abc";
goto case 4;
case 4:
string Team = arguments[3] ?? "DefaultTeam";
goto case 3;
case 3:
string Project = arguments[2] ?? "MyProject";
goto case 2;
case 2:
string Market = arguments[1] ?? "en-us";
goto case 1;
case 1:
string TaskGroupName = arguments[0];
break;
case 0:
// error handling here;
}
// function body as it was
You could call it concisely like this:
CreateTaskGroup(args);

Reflection in C#

I have recently started a development in c# and want to use reflection in following situation.
If I have a Enum class as
Enum Operation
{
Read=0;
Write;
}
If I give input as
String str = "Operation.Write";
I shoud be able to get output as 1;
Or
if constants are defined like
const int Read=0;
const int Write=1;
If the input is
String str = "Read";
output should be 0
Please Help.
You can use Enum.Parse to have that functionality.
If we combine your proposals we can get something like this.
public static Operation getOperationByName(String name) {
return Enum.Parse(typeof(Operation),name);
}
Where the name should not be null and represent the name or position in enum ie
"Read" will return Operation.Rerad and "1" will return Operation.Write
Heres the complete code to also Get the type of the Enum through Reflection without hardcoding it. The ParseConstant Method is also generic, s.t. you can use if for every Type.
namespace MyNamgespace
{
public enum Operation
{
Read = 0,
Write
}
public class ClassWithConstants
{
public const int Read = 0;
public const int Write = 1;
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine((ParseEnum("Operation.Write")));
Console.WriteLine((ParseContant<ClassWithConstants>("Write")));
Console.ReadLine();
}
static int ParseEnum(string enumValue)
{
var typeName = enumValue.Split('.')[0];
var valueName = enumValue.Split('.')[1];
var enumType = Type.GetType(string.Format("MyNamespace.{0}", typeName));
var op = (Operation) Enum.Parse(enumType, valueName);
return (int)op;
}
static int ParseContant<T>(string constantName)
{
var type = typeof (T);
var field = type.GetField(constantName, BindingFlags.Static | BindingFlags.Public);
return (int)field.GetValue(null);
}
}
}
var name = Enum.GetName(typeof(Operation), Operation.Write) //name = 'Write'
var value = Enum.Parse(typeof(Operation), "Write") //value = Operation.Write

How to get current property name via reflection?

I would like to get property name when I'm in it via reflection. Is it possible?
I have code like this:
public CarType Car
{
get { return (Wheel) this["Wheel"];}
set { this["Wheel"] = value; }
}
And because I need more properties like this I would like to do something like this:
public CarType Car
{
get { return (Wheel) this[GetThisPropertyName()];}
set { this[GetThisPropertyName()] = value; }
}
Since properties are really just methods you can do this and clean up the get_ returned:
class Program
{
static void Main(string[] args)
{
Program p = new Program();
var x = p.Something;
Console.ReadLine();
}
public string Something
{
get
{
return MethodBase.GetCurrentMethod().Name;
}
}
}
If you profile the performance you should find MethodBase.GetCurrentMethod() is miles faster than StackFrame. In .NET 1.1 you will also have issues with StackFrame in release mode (from memory I think I found it was 3x faster).
That said I'm sure the performance issue won't cause too much of a problem- though an interesting discussion on StackFrame slowness can be found here.
I guess another option if you were concerned about performance would be to create a Visual Studio Intellisense Code Snippet that creates the property for you and also creates a string that corresponds to the property name.
Slightly confusing example you presented, unless I just don't get it.
From C# 6.0 you can use the nameof operator.
public CarType MyProperty
{
get { return (CarType)this[nameof(MyProperty)]};
set { this[nameof(MyProperty)] = value]};
}
If you have a method that handles your getter/setter anyway, you can use the C# 4.5 CallerMemberName attribute, in this case you don't even need to repeat the name.
public CarType MyProperty
{
get { return Get<CarType>(); }
set { Set(value); }
}
public T Get<T>([CallerMemberName]string name = null)
{
return (T)this[name];
}
public void Set<T>(T value, [CallerMemberName]string name = null)
{
this[name] = value;
}
I'd like to know more about the context in which you need it since it seems to me that you should already know what property you are working with in the property accessor. If you must, though, you could probably use MethodBase.GetCurrentMethod().Name and remove anything after get_/set_.
Update:
Based on your changes, I would say that you should use inheritance rather than reflection. I don't know what data is in your dictionary, but it seems to me that you really want to have different Car classes, say Sedan, Roadster, Buggy, StationWagon, not keep the type in a local variable. Then you would have implementations of methods that do the proper thing for that type of Car. Instead of finding out what kind of car you have, then doing something, you then simply call the appropriate method and the Car object does the right thing based on what type it is.
public interface ICar
{
void Drive( decimal velocity, Orientation orientation );
void Shift( int gear );
...
}
public abstract class Car : ICar
{
public virtual void Drive( decimal velocity, Orientation orientation )
{
...some default implementation...
}
public abstract void Shift( int gear );
...
}
public class AutomaticTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
public class ManualTransmission : Car
{
public override void Shift( int gear )
{
...some specific implementation...
}
}
Use MethodBase.GetCurrentMethod() instead!
Reflection is used to do work with types that can't be done at compile time. Getting the name of the property accessor you're in can be decided at compile time so you probably shouldn't use reflection for it.
You get use the accessor method's name from the call stack using System.Diagnostics.StackTrace though.
string GetPropertyName()
{
StackTrace callStackTrace = new StackTrace();
StackFrame propertyFrame = callStackTrace.GetFrame(1); // 1: below GetPropertyName frame
string properyAccessorName = propertyFrame.GetMethod().Name;
return properyAccessorName.Replace("get_","").Replace("set_","");
}
FWIW I implemented a system like this:
[CrmAttribute("firstname")]
public string FirstName
{
get { return GetPropValue<string>(MethodBase.GetCurrentMethod().Name); }
set { SetPropValue(MethodBase.GetCurrentMethod().Name, value); }
}
// this is in a base class, skipped that bit for clairty
public T GetPropValue<T>(string propName)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
return GetAttributeValue<T>(attributeName);
}
public void SetPropValue(string propName, object value)
{
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
SetAttributeValue(attributeName, value);
}
private static Dictionary<string, string> PropToAttributeMap = new Dictionary<string, string>();
private string GetCrmAttributeName(string propertyName)
{
// keyName for our propertyName to (static) CrmAttributeName cache
string keyName = this.GetType().Name + propertyName;
// have we already done this mapping?
if (!PropToAttributeMap.ContainsKey(keyName))
{
Type t = this.GetType();
PropertyInfo info = t.GetProperty(propertyName);
if (info == null)
{
throw new Exception("Cannot find a propety called " + propertyName);
}
object[] attrs = info.GetCustomAttributes(false);
foreach (object o in attrs)
{
CrmAttributeAttribute attr = o as CrmAttributeAttribute ;
if (attr != null)
{
// found it. Save the mapping for next time.
PropToAttributeMap[keyName] = attr.AttributeName;
return attr.AttributeName;
}
}
throw new Exception("Missing MemberOf attribute for " + info.Name + "." + propertyName + ". Could not auto-access value");
}
// return the existing mapping
string result = PropToAttributeMap[keyName];
return result;
}
There's also a custom attribute class called CrmAttributeAttribute.
I'd strongly recommend against using GetStackFrame() as part of your solution, my original version of the solution was originally the much neater:
return GetPropValue<string>();
But it was 600x slower than the version above.
Solution # 1
var a = nameof(SampleMethod); //a == SampleMethod
var b = nameof(SampleVariable); //b == SampleVariable
var c = nameof(SampleProperty); //c == SampleProperty
Solution # 2
MethodBase.GetCurrentMethod().Name; // Name of method in which you call the code
MethodBase.GetCurrentMethod().Name.Replace("set_", "").Replace("get_", ""); // current Property
Solution # 3
from StackTrace:
public static class Props
{
public static string CurrPropName =>
(new StackTrace()).GetFrame(1).GetMethod().Name.Replace("set_", "").Replace("get_", "");
public static string CurrMethodName =>
(new StackTrace()).GetFrame(1).GetMethod().Name;
}
you just need to call Props.CurrPropName or Props.CurrMethodName
Solution # 4
Solution for .NET 4.5+:
public static class Props
{
public static string GetCallerName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
return propertyName;
}
}
usage: Props.GetCallerName();
Yes, it is!
string test = "test string";
Type type = test.GetType();
PropertyInfo[] propInfos = type.GetProperties();
for (int i = 0; i < propInfos.Length; i++)
{
PropertyInfo pi = (PropertyInfo)propInfos.GetValue(i);
string propName = pi.Name;
}
Try using System.Diagnostics.StackTrace to reflect on the call stack. The property should be somewhere in the call stack (probably at the top if you're calling it directly from the property's code).

Categories