I am attempting to create my first Razor Component in a Blazor Server-side project. The Razor Component is named MyComponent and has a property configured to retrieve its value from input:
MyComponent.razor
[Parameter]
public int Count {get; set;}
I am pulling the count from an injected service configured via IServiceCollection, which looks like this:
public interface ICountingService
{
ValueTask<int> Get();
}
The hosting page, Index.razor looks like the following:
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#Counter.Get()" />
However, I cannot seem to bind the correct value for the Count property.
I get the following error:
cannot convert from 'System.Threading.Tasks.ValueTask<int>' to 'int'
All of the examples I have found for assigning [Parameter] values to Razor Components are synchronous, and the only asynchronous values I have found are for callbacks and methods (not parameters).
Further, searching online did not return anything obvious so I am posting here in hopes of finding an answer.
Note that I am aware of using protected override async Task OnInitializedAsync and storing a value in there, but that seems like a lot of required ceremony compared to the approach above, especially when considering the multiple services and properties that I will ultimately have to bind.
So, how does one assign values from an asynchronous call to a Razor Component [Parameter] property in the way that I would prefer?
The problem is, Counter.Get() isn't an int value; it's a Task that will have an int at some undefined point either now or in the future. So you can't assign its value to something that's expecting an int right now, because that int doesn't necessarily exist yet.
You've already got the answer, and though it "seems like a lot of ceremony", it's really the only way to do this:
Create an int property to hold the value.
Declare an async method
In that method, assign the awaited value of Counter.Get() to the int that's holding the value
Set the component's Count property equal to the int property
It may feel like a lot of ceremony, but you should be grateful. Asynchrony is inherently very complicated, and having async/await available already takes care of about 95% of the hard work for you. If you think this solution is messy, you oughtta see what it would take to get it right without async/await!
Try this.
#page "/"
#inject ICountingService Counter
<h1>Hello World!</h1>
<MyComponent Count="#CounterValue" />
#code{
public int CounterValue {get; set;}
protected override async Task OnInitializedAsync()
{
CounterValue = await Counter.Get();
}
}
After #mason-wheeler and #rich-bryant provided their answers, I went to think about this a little more and found my solution, which I have posted here:
https://github.com/Mike-E-angelo/Blazor.ViewProperties
I am calling it a ViewProperty which looks like the following:
public interface IViewProperty
{
ValueTask Get();
}
public sealed class ViewProperty<T> : IViewProperty
{
public static implicit operator ViewProperty<T>(ValueTask<T> instance) => new ViewProperty<T>(instance);
readonly ValueTask<T> _source;
public ViewProperty(ValueTask<T> source) => _source = source;
public T Value { get; private set; }
public bool HasValue { get; private set; }
public async ValueTask Get()
{
Value = await _source;
HasValue = true;
}
public override string ToString() => Value.ToString();
}
You then pair it with a component base type that then iterates through the component's view properties and invokes their respective asynchronous operations:
public abstract class ViewPropertyComponentBase : ComponentBase
{
protected override async Task OnParametersSetAsync()
{
var properties = GetType().GetRuntimeProperties();
foreach (var metadata in properties.Where(x => x.GetCustomAttributes<ParameterAttribute>().Any() &&
typeof(IViewProperty).IsAssignableFrom(x.PropertyType)))
{
if (metadata.GetValue(this) is IViewProperty property)
{
await property.Get().ConfigureAwait(false);
}
}
}
}
A sample razor component that uses the above:
MyComponent.razor
#inherits ViewPropertyComponentBase
#if (Count.HasValue)
{
<p>Your magic number is #Count.</p>
}
else
{
<p>Loading, please wait...</p>
}
#code {
[Parameter]
public ViewProperty<int> Count { get; set; }
}
The resulting use is a clean view with direct bindings and no need for overrides or other additional ceremony:
#page "/"
#inject ICounter Count
<h1>Hello, world!</h1>
Welcome to your new app.
<MyComponent Count="#Count.Count()" />
(NOTE that my posted example and above uses reflection, which is slow. In the actual version of the solution that I am using, I compile the member access as lambda expressions and cache the result. You can find that by starting here if you are brave enough to poke around.)
It feels a bit hacky, but you could do something like this:
<MyComponent Count="#Counter.Get().Result" />
Related
I just started learning how to make websites with using Blazor template. But I don't know how to pass the data from one page to another. It is a bit different than .NET CORE MVC web application and I couldn't find an example for this.
<p>Solve This problem: #rnd1 * #rnd2 = ?</p>
<input type="text" name="result" bind="#result" />
<input type="button" onclick="#calculate" value="Submit" />
I want to send the value in my textbox to the another page. How can I do this?
You can pass it as a parameter.
In the page you want to navigate to, add the parameter to your route:
#page "/navigatetopage/{myvalue}"
and make sure the parameter exists in that page:
[Parameter]
private string myvalue{ get; set; }
In the same page you can pick that up in:
protected override void OnParametersSet()
{
//the param will be set now
var test = myvalue;
}
Now in your start page make sure to navigate to the second page including the value:
uriHelper.NavigateTo($"/navigatetopage/{result}");
That uriHelper needs to be injected like this:
#inject Microsoft.AspNetCore.Blazor.Services.IUriHelper uriHelper
UPDATE PREVIEW-9
on preview-9 you should use navigationManager instead of uriHelper, it also has a NavigateTo method
#inject Microsoft.AspNetCore.Components.NavigationManager navigationManager
More recent versions support the following:
The page you are navigating from:
<NavLink href="/somepage/1">Navigate to page 1</NavLink>
The page you are navigating to:
#page "/somepage/{childId:int}"
<h1>Some Page</h1>
<p role="status">Current child: #childId</p>
#code {
[Parameter]
public int childId { get; set; }
}
I personally prefer to add query string to the url.
For example when I want to pre-select tab when page is loaded:
Call the url like http://localhost:5000/profile?TabIndex=2
In your code you can parse this using NavigationManager and QueryHelpers
Add using Microsoft.AspNetCore.WebUtilities;
Then override one of the lifecycle methods and parse the query parameter
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
Uri uri = this.Nav.ToAbsoluteUri(this.Nav.Uri);
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("TabIndex", out StringValues values))
{
if (values.SafeAny())
{
_ = int.TryParse(values.First(), out int index);
this.TabIndex = index;
}
}
}
}
I got an error while testing Flores answer in the page were we passing a data
Below is the current Page
#inject Microsoft.AspNetCore.Components.NavigationManager navigationManager
Int64 Id {get;set;}
<MudMenuItem #onclick="#(() => NextPage(#Id))">Next Page</MudMenuItem>
//So Here I am passing the ID which is long
private void NextPage(Int64 Id){
navigationManager.NavigateTo($"/secondPage/{Id}");
}
Second Page
Instead of using -Id only you need to cast it to long or else it throws an error
-From
#page "/pettyCashAuditTrail/{Id}"
-To
#page "/pettyCashAuditTrail/{Id:long}"
[Parameter] public Int64 Id{ get; set; }
So far, i don't think ViewComponent solves that neither does TagHelper. Is there any replacement to this? Something that takes parameters and returns a HtmlString?
I don't see anything harmful with:
#helper foo(string something) {
<div>Say #something</div>
}
var emailbody = classfilenameinAppCodefolder.foo("hello"); //store result in a variable for further processes
For now i believe its a temporary delete before RC. https://github.com/aspnet/Razor/issues/281 and https://github.com/aspnet/Mvc/issues/1130 Well! it better be. I hope someone is working on it. Without #helper, building large HtmlString or 'template' would be a serious pain.
Note: Partial View doesn't seem to do the trick. I think it only renders views not return view to variable.
Secondly, what happened to the App_Code folder?
According to the following Github issue, it looks like #helper is coming back and will be included in asp .net core 3.0.0 preview 4.
https://github.com/aspnet/AspNetCore/issues/5110
UPDATE
Starting in asp .net core 3, you can now define a local function within a Razor code block.
#{
void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#razor-code-blocks
Alternatively you can use the #functions directive like this:
#{
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
#functions {
private void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#functions
#{
Func<String, IHtmlContent> foo = #<div>Say #item</div>;
}
I'd like to expand on #Alexaku's answer and show how I've implemented a helper like function. It's only useful on one specific page but it allows you to execute a piece of razor code multiple times with input parameters. The syntax is not great but I've found it very useful in the absence of razor's #helper function. First declare some kind of Dto that will contain the input parameters into the function.
#functions {
private class Dto
{
public string Data { get;set; }
}
}
Then declare the razor function. Note that the displayItem value can be multi-line and also note that you access the Dto variable using the #item.
#{
Func<Dto, IHtmlContent> displayItem = #<span>#item.Data</span>;
}
Then when you want to use the razor template you can call it like the following from anywhere in the page.
<div>
#displayItem(new Dto {Data = "testingData1" });
</div>
<div>
#displayItem(new Dto {Data = "testingData2" });
</div>
For .NET Core 3, you can use local functions:
#{
void RenderName(string name)
{
<p>Name: <strong>#name</strong></p>
}
RenderName("Mahatma Gandhi");
RenderName("Martin Luther King, Jr.");
}
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-3.1#razor-code-blocks
As #scott pointed out in his answer, local functions are finally available as of .NET Core 3. In prior versions one can resort to templated Razor delegates.
But none of the answers addresses the question "what happened to the App_Code folder?" The aforementioned features are local solutions, that is, helper functions defined in these ways cannot be shared between multiple views. But global helper functions could often be more convenient than the solutions MS provide out-of-the-box for view-related code re-use. (Tag helpers, partial views, view components all have their cons.) This was thoroughly discussed in this and this GitHub issue. According to these discourses, unfortunately, there's not much understanding from MS's side, so not much hope is left that this feature will be added any time soon, if ever.
However, after digging into the framework sources, I think, I could come up with a viable solution to the problem.
The core idea is that we can utilize the Razor view engine to look up an arbitrary view for us: e.g. a partial view which defines some local functions we want to use globally. Once we manage to get hold of a reference to this view, nothing prevents us from calling its public methods.
The GlobalRazorHelpersFactory class below encapsulates this idea:
public interface IGlobalRazorHelpersFactory
{
dynamic Create(string helpersViewPath, ViewContext viewContext);
THelpers Create<THelpers>(ViewContext viewContext) where THelpers : class;
}
public class GlobalRazorHelpersOptions
{
public Dictionary<Type, string> HelpersTypeViewPathMappings { get; } = new Dictionary<Type, string>();
}
public sealed class GlobalRazorHelpersFactory : IGlobalRazorHelpersFactory
{
private readonly ICompositeViewEngine _viewEngine;
private readonly IRazorPageActivator _razorPageActivator;
private readonly ConcurrentDictionary<Type, string> _helpersTypeViewPathMappings;
public GlobalRazorHelpersFactory(ICompositeViewEngine viewEngine, IRazorPageActivator razorPageActivator, IOptions<GlobalRazorHelpersOptions>? options)
{
_viewEngine = viewEngine ?? throw new ArgumentNullException(nameof(viewEngine));
_razorPageActivator = razorPageActivator ?? throw new ArgumentNullException(nameof(razorPageActivator));
var optionsValue = options?.Value;
_helpersTypeViewPathMappings = new ConcurrentDictionary<Type, string>(optionsValue?.HelpersTypeViewPathMappings ?? Enumerable.Empty<KeyValuePair<Type, string>>());
}
public IRazorPage CreateRazorPage(string helpersViewPath, ViewContext viewContext)
{
var viewEngineResult = _viewEngine.GetView(viewContext.ExecutingFilePath, helpersViewPath, isMainPage: false);
var originalLocations = viewEngineResult.SearchedLocations;
if (!viewEngineResult.Success)
viewEngineResult = _viewEngine.FindView(viewContext, helpersViewPath, isMainPage: false);
if (!viewEngineResult.Success)
{
var locations = string.Empty;
if (originalLocations.Any())
locations = Environment.NewLine + string.Join(Environment.NewLine, originalLocations);
if (viewEngineResult.SearchedLocations.Any())
locations += Environment.NewLine + string.Join(Environment.NewLine, viewEngineResult.SearchedLocations);
throw new InvalidOperationException($"The Razor helpers view '{helpersViewPath}' was not found. The following locations were searched:{locations}");
}
var razorPage = ((RazorView)viewEngineResult.View).RazorPage;
razorPage.ViewContext = viewContext;
// we need to save and restore the original view data dictionary as it is changed by IRazorPageActivator.Activate
// https://github.com/dotnet/aspnetcore/blob/v3.1.6/src/Mvc/Mvc.Razor/src/RazorPagePropertyActivator.cs#L59
var originalViewData = viewContext.ViewData;
try { _razorPageActivator.Activate(razorPage, viewContext); }
finally { viewContext.ViewData = originalViewData; }
return razorPage;
}
public dynamic Create(string helpersViewPath, ViewContext viewContext) => CreateRazorPage(helpersViewPath, viewContext);
public THelpers Create<THelpers>(ViewContext viewContext) where THelpers : class
{
var helpersViewPath = _helpersTypeViewPathMappings.GetOrAdd(typeof(THelpers), type => "_" + (type.Name.StartsWith("I", StringComparison.Ordinal) ? type.Name.Substring(1) : type.Name));
return (THelpers)CreateRazorPage(helpersViewPath, viewContext);
}
}
After introducing the singleton IGlobalRazorHelpersFactory service to DI, we could inject it in views and call the Create method to acquire an instance of the view which contains our helper functions.
By using the #implements directive in the helper view, we can even get type-safe access:
#inherits Microsoft.AspNetCore.Mvc.Razor.RazorPage
#implements IMyGlobalHelpers
#functions {
public void MyAwesomeGlobalFunction(string someParam)
{
<div>#someParam</div>
}
}
(One can define the interface type to view path mappings explicitly by configuring the GlobalRazorHelpersOptions in the ordinary way - by services.Configure<GlobalRazorHelpersOptions>(o => ...) - but usually we can simply rely on the naming convention of the implementation: in the case of the IMyGlobalHelpers interface, it will look for a view named _MyGlobalHelpers.cshtml at the regular locations. Best to put it in /Views/Shared.)
Nice so far but we can do even better! It'd be much more convenient if we could inject the helper instance directly in the consumer view. We can easily achieve this using the ideas behind IOptions<T>/HtmlLocalizer<T>/ViewLocalizer:
public interface IGlobalRazorHelpers<out THelpers> : IViewContextAware
where THelpers : class
{
THelpers Instance { get; }
}
public sealed class GlobalRazorHelpers<THelpers> : IGlobalRazorHelpers<THelpers>
where THelpers : class
{
private readonly IGlobalRazorHelpersFactory _razorHelpersFactory;
public GlobalRazorHelpers(IGlobalRazorHelpersFactory razorHelpersFactory)
{
_razorHelpersFactory = razorHelpersFactory ?? throw new ArgumentNullException(nameof(razorHelpersFactory));
}
private THelpers? _instance;
public THelpers Instance => _instance ?? throw new InvalidOperationException("The service was not contextualized.");
public void Contextualize(ViewContext viewContext) => _instance = _razorHelpersFactory.Create<THelpers>(viewContext);
}
Now we have to register our services in Startup.ConfigureServices:
services.AddSingleton<IGlobalRazorHelpersFactory, GlobalRazorHelpersFactory>();
services.AddTransient(typeof(IGlobalRazorHelpers<>), typeof(GlobalRazorHelpers<>));
Finally, we're ready for consuming our global Razor functions in our views:
#inject IGlobalRazorHelpers<IMyGlobalHelpers> MyGlobalHelpers;
#{ MyGlobalHelpers.Instance.MyAwesomeGlobalFunction("Here we go!"); }
This is a bit more complicated than the original App_Code + static methods feature but I think this is the closest we can get. According to my tests, the solution also works nicely with runtime compilation enabled. I haven't had the time so far to do benchmarks but, in theory, it should generally be faster than using partial views as the shared view is looked up only once per consumer view and after that it's just plain method calls. I'm not sure about tag helpers though. It'd be interesting to do some benchmarks comparing them. But I leave that up to the adopter.
(Tested on .NET Core 3.1.)
Update
You can find a working demo of this concept in my ASP.NET boilerplate project:
Infrastructure (relevant files are only those whose name contains GlobalRazorHelpers)
Registration
Helper interface sample
Helper implementation sample
Usage sample
The #helper directive was removed since it was incomplete and its current design did not fit in the new 'ASP.NET 5 way'. One of the reasons is that helpers should be declared in the App_Code folder while ASP.NET 5 has no concept of special folders. Therefore the team decided to temporarily remove the feature.
There are plans to bring it back in the future though. See this and this.
You can easily replace that "feature" with a ViewComponent (and a TagHelper if you want). ASP.NET Core is much more friendly to web designers, and the ViewComponents allow you to write HTML without any (weird to most) razor code.
For example:
Create a SayComponent : ViewComponent class:
public class SayComponent : ViewComponent
{
public void Render(string message)
{
return View(message);
}
}
Create a View file under Views/Shared/Say/Default.cshtml with just
#model string
<div>Message: #Model.</div>
And call it:
#await Component.RenderAsync("Say", "some message")
For a better experience, add this to your _ViewImports.cshtml file:
#addTagHelper *, YourSolutionName
And then you can use it as a tag helper:
<vc:say message="some message"></vc:say>
How about using partials to recreate reusable tags?
MyProject/Views/Shared/_foo.cshtml
#model string
<div>#Model</div>
MyProject/Views/Courses/Index.cshtml
#{
Layout = "_Layout";
}
<div>
<partial name="_foo" model="foo" />
<partial name="_foo" model="bar" />
<partial name="_foo" model="baz" />
</div>
Most of my components are registered using the code-based (fluent) approach, but there is one particular component that I need to resolve differently at runtime. This is the interface and a couple of concrete implementations:-
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
Some of our users will need the serial service while others will need the TCP service. My current solution (which works btw) is to use a typed factory and a custom component selector - the latter reads an app.config setting to determine which implementation the typed factory will resolve and return.
First the typed factory (nothing special about this):-
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
Next, the custom component selector, which reads the fully-qualified type name from app.config (e.g. "MyApp.SomeNamespace.TcpCommsService"):-
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
Then the registration stuff:-
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
Finally, an example class with a dependency on ICommsService:-
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
As already mentioned, the above solution does work, but I don't like having to inject the factory. It would be more intuitive if I could just inject an ICommsService, and let something somewhere figure out which implementation to resolve and inject - similar to what I'm doing now but earlier in Windsor's "resolving pipeline". Is something like that possible?
You can use UsingFactoryMethod here:
container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));
You can inject ICommsService to any class now. ICommsServiceFactory can be a simple interface now:
interface ICommsServiceFactory
{
ICommsService Create();
}
I'm using EF 4.1 Code First. I have an entity defined with a property like this:
public class Publication
{
// other stuff
public virtual MailoutTemplate Template { get; set; }
}
I've configured this foreign key using fluent style like so:
modelBuilder.Entity<Publication>()
.HasOptional(p => p.Template)
.WithMany()
.Map(p => p.MapKey("MailoutTemplateID"));
I have an MVC form handler with some code in it that looks like this:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
In this case, we're updating an existing Publication entity, so we're going through the else path. When the _unitOfWork.Commit() fires, an UPDATE is sent to the database that I can see in SQL Profiler and Intellitrace, but it does NOT include the MailoutTemplateID in the update.
What's the trick to get it to actually update the Template?
Repository Code:
public virtual void Update(TEntity entity)
{
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual TEntity Get(int id)
{
return _dbSet.Find(id);
}
UnitOfWork Code:
public void Commit()
{
_dbContext.SaveChanges();
}
depends on your repository code. :) If you were setting publication.Template while Publication was being tracked by the context, I would expect it to work. When you are disconnected and then attach (with the scenario that you have a navigation property but no explicit FK property) I'm guessing the context just doesn't have enough info to work out the details when SaveChanges is called. I'd do some experiments. 1) do an integration test where you query the pub and keep it attached to the context, then add the template, then save. 2) stick a MailOutTemplateId property on the Publicaction class and see if it works. Not suggesting #2 as a solution, just as a way of groking the behavior. I"m tempted to do this experiment, but got some other work I need to do. ;)
I found a way to make it work. The reason why I didn't initially want to have to do a Get() (aside from the extra DB hit) was that then I couldn't do this bit of AutoMapper magic to get the values:
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
However, I found another way to do the same thing that doesn't use a return value, so I updated my method like so and this works:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = _publicationRepository.Get(publicationEditViewModel.Id);
_mappingEngine.Map(publicationEditViewModel, publication);
// publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
I'm injecting an IMappingEngine now into the class, and have wired it up via StructureMap like so:
For<IMappingEngine>().Use(() => Mapper.Engine);
For more on this, check out Jimmy's AutoMapper and IOC post.
I'm working through the book Head First C# (and it's going well so far), but I'm having a lot of trouble wrapping my head around the syntax involved with using the "this." keyword.
Conceptually, I get that I'm supposed to use it to avoid having a parameter mask a field of the same name, but I'm having trouble actually tracking it through their examples (also, they don't seem to have a section dedicated to that particular keyword, they just explain it and start using it in their examples).
Does anyone have any good rules of thumb they follow when applying "this."? Or any tutorials online that explain it in a different way that Head First C#?
Thanks!
Personally I only use it when I have to which is:
Constructor chaining:
public Foo(int x) : this(x, null)
{
}
public Foo(int x, string name)
{
...
}
Copying from a parameter name into a field (not as common in C# as in Java, as you'd usually use a property - but common in constructors)
public void SetName(string name)
{
// Just "name = name" would be no-op; within this method,
// "name" refers to the parameter, not the field
this.name = name;
}
Referring to this object without any members involved:
Console.WriteLine(this);
Declaring an extension method:
public static TimeSpan Days(this int days)
{
return TimeSpan.FromDays(days);
}
Some other people always use it (e.g. for other method calls) - personally I find that clutters things up a bit.
StyleCop's default coding style enforces the following rule:
A1101: The call to {method or property
name} must begin with the 'this.'
prefix to indicate that the item is a
member of the class.
Which means that every method, field, property that belongs to the current class will be prefixed by this. I was initially resistant to this rule, which makes your code more verbose, but it has grown on me since, as it makes the code pretty clear. This thread discusses the question.
I write this. if and only if it enhances readability, for example, when implementing a Comparable interface (Java, but the idea is the same):
public void compareTo(MyClass other) {
if (this.someField > other.someField) return 1;
if (this.someField < other.someField) return -1;
return 0;
}
As to parameter shadowing (e.g. in constructors): I usually give those a shorter name of the corresponding field, such as:
class Rect {
private int width, height;
public Rect(int w, int h) {
width = w;
height = h;
}
}
Basically, this gives you a reference to the current object. You can use it to access members on the object, or to pass the current object as parameters into other methods.
It is entirely unnecessary in almost all cases to place it before accessing member variables or method calls, although some style guidelines recommend it for various reasons.
Personally, I make sure I name my member variables to be clearly different from my parameters to avoid ever having to use 'this.'. For example:
private String _someData;
public String SomeData
{
get{return _someData;}
set{_someData = value;}
}
It's very much an individual preference though, and some people will recommend that you name the property and member variable the same (just case difference - 'someData' and 'SomeData') and use the this keyword when accessing the private member to indicate the difference.
So as for a rule of thumb - Avoid using it. If you find yourself using it to distinguish between local/parameters variables and member variables then rename one of them so you don't have to use 'this'.
The cases where I would use it are multiple constructors, passing a reference to other methods and in extension methods. (See Jon's answer for examples)
If you have a method inside a class which uses same class's fields, you can use this.
public class FullName
{
public string fn { set; get; }
public string sn { set; get; }
//overriding Equals method
public override bool Equals(object obj)
{
if (!(obj is FullName))
return false;
if (obj == null)
return false;
return this.fn == ((FullName)obj).fn &&
this.sn == ((FullName)obj).sn;
}
//overriding GetHashCode
public override int GetHashCode()
{
return this.fn.GetHashCode() ^ this.sn.GetHashCode();
}
}