Instantiate Null Object Inside Extension Method
I am wanting to know if it's possible to instantiate a null object inside of an extension method for that object.
Example:
Simple class
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
Extension Method
public static class ExtensionMethods
{
public static void GetTestClass(this TestClass tc, string name)
{
using (SqlConnection cn = new SqlConnection(myConnectionString))
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText= "SELECT Name, Age FROM Person WHERE Name = @Name";
开发者_开发问答 cn.Open();
cmd.Parameters.AddWithValue("@Name", name);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
tc = new TestClass();
tc.Name = name;
tc.Age = int.Parse(dr["Age"]);
}
}
}
}
}
The user is going to give me a name, and I want to validate that the name exists by doing this...
static void Main(string[] args)
{
TestClass tc = null;
tc.GetTestClass("Some Name");
if (tc == null)
{
Console.WriteLine("Not Found");
}
Console.Read();
}
Is this possible? My current code leaves the original object as null. I didn't know if I was doing something wrong of it this was just not possible.
Thanks.
This cannot work, you need a method that returns an object. Assigning the this argument in an extension method won't do what you want it to do, it isn't going to modify the tc
variable.
You might be falling victim to the trappings of IntelliSense here, yes it is going to show you the GetTestClass() method. But the code you'd have to write doesn't pass the right side code review door:
tc = tc.GetTestClass("some name");
Clearly you want a static factory method here:
tc = Mumble.CreateTest("some name");
I agree with @Stuart. It looks like you are hoping that the extension method will overwrite the current instance of the class with something retrieved by the database.
Either you need to remove the tc = new TestClass();
in the read loop or rewrite this extension class as a static factory method on TestClass
or maybe a TestClassFactory
.
No - this code doesn't make sense:
TestClass tc = null;
tc.GetTestClass("Some Name");
This could looks like it should throw a NullReferenceException
...
OK - so it doesn't (see example on http://www.pvle.be/2008/11/extension-methods-and-null-objects/) but it also doesn't pass tc in by ref
either... so it won't update tc
for you
MSDN on extensions says:
In general, we recommend that you implement extension methods sparingly and only when you have to. Whenever possible, client code that must extend an existing type should do so by creating a new type derived from the existing type.
http://msdn.microsoft.com/en-us/library/bb383977.aspx
IMO it would be better to implement what you are looking for as some sort of Factory method.
Or you could use something like:
TestClass tc = new TestClass();
if (tc.TryFillFrom("Some Name"))
{
// do stuff
}
else
{
// handle missing error
}
or you could use a FillFrom
method which throws some NotFoundException
No, that is not possible.
It's only a copy of the reference from the variable that is sent to the method, so you can't change the contents of the variable.
It wouldn't be intuitive to use an extension method like that, anyway. Eventhough you can call an extension method on a null reference, your method would rely on it.
Just use a regular static method instead, and return null if the record is not found:
TestClass tc = TestClass.GetTestClass("Some Name");
It is possible, but when you assign to tc
, the assignment only affects the parameter inside the method, not the variable passed to that parameter. It's no different to what happens with conventional parameter passing:
public static void GetTestClass(TestClass tc, string name) {
...
tc = new TestClass();
...
}
static void Main() {
TestClass tc = null;
GetTestClass(tc, "Some Name");
// The assignment to tc in GetTestClass doesn't affect the tc variable in Main.
...
}
As for a solution, avoid invoking extension methods on null references. It is obviously confusing. Just get the new object via simpler, more conventional idioms:
public static TestClass GetTestClass(string name) {
...
TestClass tc = new TestClass();
...
return tc;
}
static void Main() {
TestClass tc = GetTestClass("Some Name");
...
}
I'm surprised that everyone is offering static method solutions. If this is how your class is always instantiated, use a constructor. That's what they're for. If it's not the only way then create an empty constructor and overload it to pass in your parameters when you DO want it instantiated that way. I would prefer to have the two constructors like this
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
public TestClass() { }
public TestClass(string name)
{
using (SqlConnection cn = new SqlConnection(myConnectionString))
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText= "SELECT Name, Age FROM Person WHERE Name = @Name";
cn.Open();
cmd.Parameters.AddWithValue("@Name", name);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
Name = name;
Age = int.Parse(dr["Age"]);
}
}
}
}
}
To me, this is more straight forward. Extension methods should be used when you don't have access to a class's code to add a method of your own.
精彩评论