I've got a couple of extension functions that I want to transfer between classes.
I have a class called Helpers.cs that I want to have the following:
namespace XYZ
{
public class Helpers
{
public static string Encrypt(this string plainText){
//... do encrypting
}
}
}
In my other class Impliment.cs I want to have the following:
string s = "attack";
s.Encrypt();
How can I implement this?
You're close - extension methods need to be in a static class:
public static class Helpers
{
public static string Encrypt(this string plainText){
//... do encrypting
}
}
If you tried what you posted you'd get a pretty clear compiler error that says basically the same thing:
Extension method must be defined in a non-generic static class
Note that your usage will be slightly different that what you want. You can't do:
string s = "attack";
s.Encrypt();
becasue strings are immutable. Best you can do is overwrite the existing varialbe or store the result in a new one:
string s = "attack";
s = s.Encrypt(); // overwrite
or
string s = "attack";
string s2 = s.Encrypt(); // new variable
You need to make the class, static as well and use a using statement.
Example
FileA.cs:
namespace XYZ {
public static class Helpers {
public static string Encrypt(this string plainText){
//... do encrypting
return plainText;
}
}
}
FileB.cs:
using XYZ;
public class MainClass {
public static void Main() {
string s = "input";
s = s.Encrypt();
Console.WriteLine(s);
}
}
To create an Extension Method, the class must be static, but in general it has to follow these rules:
The class must be public and static
The method must be public and static
The type you want to create the extension method, in C#, must have the first parameter with the this keyword before the parameter
In your case, change the class to be static , for sample:
public static class Helpers
{
public static string Encrypt(this string plainText)
{
//... do encrypting
// return a string;
}
}
I also like to create the classes with name like Type and Extensions sufix, for sample: StringExtensions.cs, DateTimeExtensions.cs, etc.
Obs: Remember it is not a type method, it is just a static method, but you use as a method from a type.
Related
I'm trying to use extension method, but the method is defined twice with same name.
Let's say A.Extensions.Ext() and B.Extensions.Ext() I need both references in my class and when trying
using A.Extensions;
using B.Extensions;
class C
{
public void Main()
{
somevalue.Ext();
}
}
I want to somehow define which method to use and I don't know how to do that.
Thanks for help!
There is a way to choose an extension method to be used
Assume you have two classes with extension methods for string
public static class Extension1
{
public static string GetLowerCaseResult(this string str)
{
return str.ToLowerInvariant();
}
}
public static class Extension2
{
public static string GetLowerCaseResult(this string str)
{
return str.ToLowerInvariant();
}
}
to call it in Main method you have to explicitly specify class and method in this way
static void Main(string[] args)
{
var str = "QWERTY";
Extension2.GetLowerCaseResult(str);
Console.Read();
}
What's the difference between static classes, and static methods? I want to learn the differences, and when I might use one vs. the other.
For example, I have a class like this:
static class ABC
{
public int a;
public void function_a()
{
a = 10;
}
}
and another class like this:
class DEF
{
public static int a;
public static void function_a()
{
a= 10;
}
}
I have used the second type of class many times, and I know the usage. What's the usage of the first example?
Your first example will not compile, a static class must have all static members.
The difference between just using some static methods and a static class is that you are telling the compiler that the class cannot be instantiated. The second example you can create an object of the DEF class even though there are no instance methods in it. The ABC class cannot be instantiated with the new operator (will get a compile-time error).
When to Use Static Classes
Suppose you have a class CompanyInfo that contains the following methods to get information about the company name and address.
C#
class CompanyInfo
{
public string GetCompanyName() { return "CompanyName"; }
public string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
These methods do not need to be attached to a specific instance of the class. Therefore, instead of creating unnecessary instances of this class, you can declare it as a static class, like this:
C#
static class CompanyInfo
{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
Use a static class as a unit of organization for methods not associated with particular objects. Also, a static class can make your implementation simpler and faster because you do not have to create an object in order to call its methods. It is useful to organize the methods inside the class in a meaningful way, such as the methods of the Math class in the System namespace.
I have the following:
public static class CityStatusExt
{
public static string D2(this CityStatus key)
{
return ((int) key).ToString("D2");
}
public static class CityTypeExt
{
public static string D2(this CityType key)
{
return ((int) key).ToString("D2");
}
Plus other classes with similar extensions that return the key formatted as a "D2"
Is there a way I could inherit from a base class and have the base class provide the functionality so
don't I don't have to repeat the same extension method code?
Update. I am sorry I did not mention this but my classes like CityType are Enums.
You can make the method generic. C# will infer the type:
public static class Extension
{
public static string D2<T> (this T key)
{
return ((int)(object) key).ToString("D2");
}
}
From the comment below, CityType and CityStatus are enums. Therefore you can do this:
public static class Extensions
{
public static string D2(this Enum key)
{
return Convert.ToInt32(key).ToString("D2");
}
}
Original answer:
You can use a generic method and an interface ID2Able:
public static class Extensions
{
public static string D2<T>(this T key) where T : ID2Able
{
return ((int) key).ToString("D2");
}
}
This way the extension method won't show up for absolutely every type; it'll only be available for things you inherit ID2Able from.
Your enums already all inherit from a common base class, namely System.Enum. So you can do this (Enums don't accept "D2" as a format string, but they accept "D", so I added a call to PadLeft):
public static class EnumExtensions
{
public static string D2(this Enum e)
{
return e.ToString("D").PadLeft(2, '0');
}
}
I want to inherit to extend the C# string class to add methods like WordCount() and several many others but I keep getting this error:
Error 1 'WindowsFormsApplication2.myString': cannot derive from sealed
type 'string'
Is there any other way I can get past this ? I tried with string and String but it didn't work.
Another option could be to use an implicit operator.
Example:
class Foo {
readonly string _value;
public Foo(string value) {
this._value = value;
}
public static implicit operator string(Foo d) {
return d._value;
}
public static implicit operator Foo(string d) {
return new Foo(d);
}
}
The Foo class acts like a string.
class Example {
public void Test() {
Foo test = "test";
Do(test);
}
public void Do(string something) { }
}
System.String is sealed, so, no, you can't do that.
You can create extension methods. For instance,
public static class MyStringExtensions
{
public static int WordCount(this string inputString) { ... }
}
use:
string someString = "Two Words";
int numberOfWords = someString.WordCount();
If your intention behind inheriting from the string class is to simply create an alias to the string class, so your code is more self describing, then you can't inherit from string. Instead, use something like this:
using DictKey = System.String;
using DictValue= System.String;
using MetaData = System.String;
using SecurityString = System.String;
This means that your code is now more self describing, and the intention is clearer, e.g.:
Tuple<DictKey, DictValue, MetaData, SecurityString> moreDescriptive;
In my opinion, this code shows more intention compared to the same code, without aliases:
Tuple<string, string, string, string> lessDescriptive;
This method of aliasing for more self describing code is also applicable to dictionaries, hash sets, etc.
Of course, if your intention is to add functionality to the string class, then your best bet is to use extension methods.
You cannot derive from string, but you can add extensions like:
public static class StringExtensions
{
public static int WordCount(this string str)
{
}
}
What's wrong with a helper class? As your error message tells you, String is sealed, so your current approach will not work. Extension methods are your friend:
myString.WordCount();
static class StringEx
{
public static int WordCount(this string s)
{
//implementation.
}
}
You can't inherit a sealed class (that's the whole point of it) and the reason why it wouldn't work with both string and System.String is that the keyword string is simply an alias for System.String.
If you don't need to access the internals of the string class, what you can do is create an Extension Method, in your case :
//note that extension methods can only be declared in a static class
static public class StringExtension {
static public int WordCount(this string other){
//count the word here
return YOUR_WORD_COUNT;
}
}
You still won't have access to the private methods and properties of the string class but IMO it's better than writing :
StringHelper.WordCount(yourString);
That's also how LINQ works.
The string class is marked sealed because you are not supposed to inherit from it.
What you can do is implement those functions elsewhere. Either as plain static methods on some other class, or as extension methods, allowing them to look like string members.
This should hopefully be a simple one.
I would like to add an extension method to the System.Web.Mvc.ViewPage< T > class.
How should this extension method look?
My first intuitive thought is something like this:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle(this ViewPage<Type> v)
{
return "";
}
}
}
Solution
The general solution is this answer.
The specific solution to extending the System.Web.Mvc.ViewPage class is my answer below, which started from the general solution.
The difference is in the specific case you need both a generically typed method declaration AND a statement to enforce the generic type as a reference type.
I don't have VS installed on my current machine, but I think the syntax would be:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
{
return "";
}
}
}
Thanks leddt.
Doing that yielded the error:
The type 'TModel' must be a reference
type in order to use it as parameter
'TModel' in the generic type or method
which pointed me to this page, which yielded this solution:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> v)
where T : class
{
return "";
}
}
}
It just needs the generic type specifier on the function:
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<Type>(this ViewPage<Type> v)
{
return "";
}
}
}
Edit: Just missed it by seconds!
namespace System.Web.Mvc
{
public static class ViewPageExtensions
{
public static string GetDefaultPageTitle<T>(this ViewPage<T> view)
where T : class
{
return "";
}
}
}
You may also need/wish to add the "new()" qualifier to the generic type (i.e. "where T : class, new()" to enforce that T is both a reference type (class) and has a parameterless constructor.
Glenn Block has a good example of implementing a ForEach extension method to IEnumerable<T>.
From his blog post:
public static class IEnumerableUtils
{
public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach(T item in collection)
action(item);
}
}
If you want the extension to only be available for the specified type
you simply just need to specify the actual type you will be handling
something like...
public static string GetDefaultPageTitle(this ViewPage<YourSpecificType> v)
{
...
}
Note intellisense will then only display the extension method when you declare your (in this case) ViewPage with the matching type.
Also, best not to use the System.Web.Mvc namespace, I know its convenient to not have to include your namespace in the usings section, but its far more maintainable if you create your own extensions namespace for your extension functions.
Here's an example for Razor views:
public static class WebViewPageExtensions
{
public static string GetFormActionUrl(this WebViewPage view)
{
return string.Format("/{0}/{1}/{2}", view.GetController(), view.GetAction(), view.GetId());
}
public static string GetController(this WebViewPage view)
{
return Get(view, "controller");
}
public static string GetAction(this WebViewPage view)
{
return Get(view, "action");
}
public static string GetId(this WebViewPage view)
{
return Get(view, "id");
}
private static string Get(WebViewPage view, string key)
{
return view.ViewContext.Controller.ValueProvider.GetValue(key).RawValue.ToString();
}
}
You really don't need to use the Generic version as the generic one extends the non-generic one so just put it in the non-generic base class and you're done :)